La forma más sencilla de traducir sus aplicaciones Next.js (con configuración de páginas) .
Si está utilizando next-i18next (directorio de páginas) en producción y desea liberar algunos superpoderes, puede consultar esta publicación de blog.
Si está utilizando Next.js 13/14 con el directorio de aplicaciones, no es necesario next-i18next; puede usar directamente i18next y react-i18next, como se describe en esta publicación de blog.
Aunque Next.js proporciona enrutamiento internacionalizado directamente, no maneja ninguna gestión del contenido de traducción ni la funcionalidad de traducción en sí. Todo lo que hace Next.js es mantener sincronizadas sus configuraciones regionales y URL.
Para complementar esto, next-i18next
proporciona la funcionalidad restante (gestión del contenido de traducción y componentes/ganchos para traducir sus componentes de React) al mismo tiempo que es totalmente compatible con SSG/SSR, múltiples espacios de nombres, división de códigos, etc.
Si bien next-i18next
usa i18next y react-i18next internamente, los usuarios de next-i18next
simplemente necesitan incluir su contenido de traducción como archivos JSON y no tienen que preocuparse por mucho más.
Una demostración en vivo está disponible aquí. Esta aplicación de demostración es un ejemplo sencillo: nada más y nada menos.
Fácil de configurar, fácil de usar: la instalación solo requiere unos pocos pasos y la configuración es simple.
Sin otros requisitos: next-i18next
simplifica la internacionalización de su aplicación Next.js sin dependencias adicionales.
Listo para producción: next-i18next
admite pasar traducciones y opciones de configuración a páginas como accesorios con soporte SSG/SSR.
Su archivo next-i18next.config.js
proporcionará la configuración para next-i18next
. Después de la configuración, appWithTranslation
nos permite usar la función t
(traducir) en nuestros componentes mediante ganchos.
Luego agregamos serverSideTranslation
a getStaticProps o getServerSideProps (según su caso) en nuestros componentes a nivel de página.
¡Ahora nuestra aplicación Next.js es completamente traducible!
yarn add next-i18next react-i18next i18next
También debes tener instalado react
y next
.
De forma predeterminada, next-i18next
espera que sus traducciones estén organizadas de la siguiente manera:
.
└── public
└── locales
├── en
| └── common.json
└── de
└── common.json
Esta estructura también se puede ver en el ejemplo sencillo.
Si desea estructurar sus traducciones/espacios de nombres de una manera personalizada, deberá pasar los valores localePath
y localeStructure
modificados a la configuración de inicialización.
Primero, cree un archivo next-i18next.config.js
en la raíz de su proyecto. La sintaxis del objeto i18n
anidado proviene directamente de Next.js.
Esto le indica next-i18next
cuál es su defaultLocale
y otras configuraciones regionales, para que pueda precargar las traducciones en el servidor:
next-i18next.config.js
/** @type {import('next-i18next').UserConfig} */
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
}
Ahora, cree o modifique su archivo next.config.js
, pasando el objeto i18n
a su archivo next.config.js
, para habilitar el enrutamiento de URL localizado:
next.config.js
const { i18n } = require ( './next-i18next.config' )
module . exports = {
i18n ,
}
Hay tres funciones que exporta next-i18next
, que necesitarás usar para traducir tu proyecto:
Este es un HOC que envuelve tu _app
:
import { appWithTranslation } from 'next-i18next'
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp )
appWithTranslation
HOC es el principal responsable de agregar un I18nextProvider
.
Esta es una función asíncrona que debe incluir en sus componentes a nivel de página, a través de getStaticProps
o getServerSideProps
(según su caso de uso):
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
export async function getStaticProps ( { locale } ) {
return {
props : {
... ( await serverSideTranslations ( locale , [
'common' ,
'footer' ,
] ) ) ,
// Will be passed to the page component as props
} ,
}
}
Tenga en cuenta que serverSideTranslations
debe importarse desde next-i18next/serverSideTranslations
; este es un módulo separado que contiene código específico de NodeJs.
Además, tenga en cuenta que serverSideTranslations
no es compatible con getInitialProps
, ya que solo se puede ejecutar en un entorno de servidor, mientras que getInitialProps
se llama en el lado del cliente cuando se navega entre páginas.
El HOC serverSideTranslations
es el principal responsable de pasar traducciones y opciones de configuración a las páginas, como accesorios; debe agregarlo a cualquier página que tenga traducciones.
Este es el gancho que realmente utilizarás para hacer la traducción. El gancho useTranslation
proviene de react-i18next
, pero debe importarse directamente desde next-i18next
.
¡NO use la exportación useTranslation
de react-i18next
, pero SÓLO use la de next-i18next
!
import { useTranslation } from 'next-i18next'
export const Footer = ( ) => {
const { t } = useTranslation ( 'footer' )
return (
< footer >
< p > { t ( 'description' ) } < / p >
< / footer >
)
}
De forma predeterminada, next-i18next
enviará todos sus espacios de nombres al cliente en cada solicitud inicial. Este puede ser un enfoque apropiado para aplicaciones más pequeñas con menos contenido, pero muchas aplicaciones se beneficiarán al dividir los espacios de nombres según la ruta.
Para hacer eso, puede pasar una serie de espacios de nombres requeridos para cada página a serverSideTranslations
. Puede ver este enfoque en ejemplos/simple/pages/index.tsx. Pasar una matriz vacía de espacios de nombres requeridos no enviará espacios de nombres.
Nota: useTranslation
proporciona espacios de nombres para el componente en el que lo usa. Sin embargo, serverSideTranslations
proporciona el total de espacios de nombres disponibles para todo el árbol de React y pertenece al nivel de página. Ambos son necesarios.
De forma predeterminada, next-i18next
enviará solo la configuración regional activa al cliente en cada solicitud. Esto ayuda a reducir el tamaño de la carga útil inicial enviada al cliente. Sin embargo, en algunos casos es posible que también se necesiten traducciones para otros idiomas en tiempo de ejecución. Por ejemplo, cuando se utiliza getFixedT del gancho useTranslation
.
Para cambiar el comportamiento y cargar configuraciones regionales adicionales, simplemente pase una serie de configuraciones regionales como último argumento a serverSideTranslations
.
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
export async function getStaticProps({ locale }) {
return {
props: {
- ...(await serverSideTranslations(locale, ['common', 'footer'])),
+ ...(await serverSideTranslations(locale, ['common', 'footer'], null, ['en', 'no'])),
},
};
}
Como resultado, las traducciones de no
y en
local siempre se cargarán independientemente del idioma actual.
Nota: El argumento adicional debe agregarse a todas las páginas que usan la función
getFixedT
.
De forma predeterminada, next-i18next
agregará defaultLocale
como alternativa. Para cambiar esto, puede configurar fallbackLng
. Todos los valores admitidos por i18next
( string
, array
, object
y function
) también son compatibles con next-i18next
.
Además, nonExplicitSupportedLngs
se puede establecer en true
para admitir todas las variantes de un idioma, sin la necesidad de proporcionar archivos JSON para cada una de ellas. Tenga en cuenta que todas las variantes aún deben incluirse en locales
para habilitar el enrutamiento dentro de next.js
Nota:
fallbackLng
ynonExplicitSupportedLngs
se pueden utilizar al mismo tiempo. Solo hay una excepción: no puede usar una función parafallbackLng
cuandononExplicitSupportedLngs
estrue
.
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'fr' , 'de-AT' , 'de-DE' , 'de-CH' ] ,
} ,
fallbackLng : {
default : [ 'en' ] ,
'de-CH' : [ 'fr' ] ,
} ,
nonExplicitSupportedLngs : true ,
// de, fr and en will be loaded as fallback languages for de-CH
}
Tenga en cuenta que el uso fallbackLng
y nonExplicitSupportedLngs
puede aumentar fácilmente el tamaño inicial de la página.
Para su información: establecer fallbackLng
en false
NO serializará su idioma alternativo (generalmente defaultLocale
). Esto disminuirá el tamaño de la carga inicial de la página.
Si necesita modificar opciones de configuración más avanzadas, puede pasarlas a través de next-i18next.config.js
. Por ejemplo:
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
localePath :
typeof window === 'undefined'
? require ( 'path' ) . resolve ( './my-custom/path' )
: '/public/my-custom/path' ,
ns : [ 'common' ] ,
}
Algunos complementos i18next
(que puede pasar a config.use
) no son serializables, ya que contienen funciones y otras primitivas de JavaScript.
Puede encontrarse con esto si su caso de uso es más avanzado. Verás que Next.js arroja un error como:
Error: Error serializing `._nextI18Next.userConfig.use[0].process` returned from `getStaticProps` in "/my-page".
Reason: `function` cannot be serialized as JSON. Please only return JSON serializable data types.
Para solucionar este problema, deberá configurar config.serializeConfig
en false
y pasar manualmente su configuración a appWithTranslation
:
import { appWithTranslation } from 'next-i18next'
import nextI18NextConfig from '../next-i18next.config.js'
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp , nextI18NextConfig )
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import nextI18NextConfig from '../next-i18next.config.js'
export const getStaticProps = async ( { locale } ) => ( {
props : {
... ( await serverSideTranslations (
locale ,
[ 'common' , 'footer' ] ,
nextI18NextConfig
) ) ,
} ,
} )
Cuando se utiliza en páginas generadas en el lado del servidor con getStaticPaths
y fallback: true
o fallback: 'blocking'
, la configuración predeterminada indicada anteriormente hará que la aplicación se desmonte y se vuelva a montar en cada carga, lo que provocará varias consecuencias adversas, como llamar a cada useEffect(() => {...}, [])
gancho dos veces y ligera degradación del rendimiento.
Esto se debe al hecho de que, para esas páginas, Next.js realiza un primer renderizado con serverSideProps
vacíos y luego un segundo renderizado con serverSideProps
que incluye las traducciones next-i18next
. Con la configuración predeterminada, la instancia i18n
inicialmente undefined
cuando serverSideProps
está empty
, lo que provoca el proceso de desmontaje y montaje.
Para mitigar este problema, puede hacer lo siguiente:
import { UserConfig } from 'next-i18next' ;
import nextI18NextConfig from '../next-i18next.config.js'
const emptyInitialI18NextConfig : UserConfig = {
i18n : {
defaultLocale : nextI18NextConfig . i18n . defaultLocale ,
locales : nextI18NextConfig . i18n . locales ,
} ,
} ;
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp , emptyInitialI18NextConfig ) // Makes sure the initial i18n instance is not undefined
Esto funcionará siempre y cuando se asegure de que, en el estado de la página alternativa, su código del lado del cliente no intente mostrar ninguna traducción, ya que de lo contrario obtendrá un error de "no coincidencia entre el servidor y el cliente" de Next.js (debido a la hecho de que el servidor tiene una traducción real en su html mientras que el html del cliente tiene la clave de traducción en el mismo lugar).
Esto es normal y está bien: ¡no deberías mostrarle una clave de traducción a tu usuario de todos modos!
Desde v11.0.0 next-i18next también brinda soporte para la carga de traducciones del lado del cliente.
En algunos casos de uso, es posible que desee cargar un archivo de traducción dinámicamente sin tener que utilizar serverSideTranslations
. Esto puede ser especialmente útil para componentes con carga diferida que no desea que ralenticen las páginas.
Puede encontrar más información al respecto aquí.
Debido a que los recursos se cargan una vez cuando se inicia el servidor, cualquier cambio realizado en sus archivos JSON de traducción en desarrollo no se cargará hasta que se reinicie el servidor.
En producción, esto no suele ser un problema, pero en desarrollo es posible que desees ver actualizaciones de tus archivos JSON de traducción sin tener que reiniciar tu servidor de desarrollo cada vez. Para hacer esto, configure la opción de configuración reloadOnPrerender
en true
.
Esta opción recargará sus traducciones cada vez que se llame serverSideTranslations
(en getStaticProps
o getServerSideProps
). Si está utilizando serverSideTranslations
en getServerSideProps
, se recomienda deshabilitar reloadOnPrerender
en entornos de producción para evitar recargar recursos en cada llamada al servidor.
Llave | Valor predeterminado | Nota |
---|---|---|
defaultNS | 'common' | |
localePath | './public/locales' | Puede ser una función, consulte la nota a continuación. (también puede ser nulo, si se pasa la opción de recursos directamente a través de la configuración, como aquí) |
localeExtension | 'json' | Se ignora si localePath es una función. |
localeStructure | '{{lng}}/{{ns}}' | Se ignora si localePath es una función. |
reloadOnPrerender | false | |
serializeConfig | true | |
use (para complementos) | [] | |
onPreInitI18next | undefined | es decir (i18n) => i18n.on('failedLoading', handleFailedLoading) |
localePath
como función tiene la forma (locale: string, namespace: string, missing: boolean) => string
que devuelve la ruta completa, incluido el nombre del archivo y la extensión. Cuando missing
es verdadero, devuelve la ruta para la opción addPath
de i18next-fs-backend
; cuando es falso, devuelve la ruta para la opción loadPath
. Más información en el repositorio i18next-fs-backend
.
Si localePath es una función, asegúrese de definir también la opción ns, porque en el lado del servidor no podemos precargar los espacios de nombres en ese momento.
Todas las demás opciones de i18next y reaccionar-i18next también se pueden pasar.
También puede pasar los resources
directamente en combinación con configurar localePath
en null
.
De forma predeterminada, i18next usa {{
como prefijo y }}
como sufijo para la interpolación. Si desea o necesita anular estas configuraciones de interpolación, también debe especificar una configuración localeStructure
alternativa que coincida con su prefijo y sufijo personalizados.
Por ejemplo, si desea utilizar {
y }
la configuración se vería así:
{
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'nl' ] ,
} ,
interpolation : {
prefix : '{' ,
suffix : '}' ,
} ,
localeStructure : '{lng}/{ns}' ,
}
next-i18next.config.js
Si desea cambiar la ruta de configuración predeterminada, puede configurar la variable de entorno I18NEXT_DEFAULT_CONFIG_PATH
.
Por ejemplo, dentro del archivo .env
puedes establecer una ruta estática:
I18NEXT_DEFAULT_CONFIG_PATH=/path/to/project/apps/my-app/next-i18next.config.js
O puedes usar un truco para la ruta dinámica y configurar lo siguiente dentro de next.config.js
:
process . env . I18NEXT_DEFAULT_CONFIG_PATH = ` ${ __dirname } /next-i18next.config.js` ;
// ... Some other imports
const { i18n } = require ( './next-i18next.config' ) ;
// ... Some other code
module . exports = {
i18n ,
...
} ;
Esto significa que el archivo de configuración de i18n estará en el mismo directorio que next.config.js
y no importa dónde esté su directorio de trabajo actual. Esto ayuda, por ejemplo, para nx
cuando tiene monorepo e inicia su aplicación desde la raíz del proyecto pero la aplicación está en apps/{appName}
.
Aviso Si su configuración next-i18next.config.js
no está en el mismo directorio que next.config.js
, debe copiarla manualmente (o mediante un script personalizado).
Si planea agregar next-i18next de forma incremental a su proyecto, le recomendamos que pase su next-i18next.config
a appWithTranslation
para evitar problemas.
es decir
import nextI18nextConfig from '../../next-i18next.config' ;
//...
export default appWithTranslation ( MyApp , nextI18nextConfig ) ;
Consulte el número 2259 para obtener más información.
Es posible que algunas PaaS sin servidor no puedan localizar la ruta de sus traducciones y requieran una configuración adicional. Si tiene problemas con el sistema de archivos al utilizar serverSideTranslations
, configure config.localePath
para usar path.resolve
. Puede encontrar un ejemplo aquí.
Para la implementación de Docker, tenga en cuenta que si utiliza el Dockerfile
de los documentos de Next.js, no olvide copiar next.config.js
y next-i18next.config.js
en la imagen de Docker.
COPY --from=builder /app/next.config.js ./next.config.js
COPY --from=builder /app/next-i18next.config.js ./next-i18next.config.js
Si elige utilizar un backend i18next diferente al backend i18next-fs integrado, deberá asegurarse de que los recursos de traducción estén cargados antes de llamar a la función t
. Dado que React suspense aún no es compatible con SSR, esto se puede resolver de 2 maneras diferentes:
1) Precargar los espacios de nombres:
Configure la opción ns
, como en este ejemplo. Hacer esto garantizará que todos los recursos de traducción se carguen en la inicialización.
2) Verifique la bandera listo:
Si no puede o no quiere proporcionar la matriz ns
, las llamadas a la función t
harán que los espacios de nombres se carguen sobre la marcha. Esto significa que deberá controlar el estado "no listo" marcando ready === true
o props.tReady === true
. No hacerlo resultará en que sus traducciones se muestren antes de que se carguen, lo que provocará que se llame a "guardar faltante" a pesar de que las traducciones realmente existen (aún no están cargadas). Esto se puede hacer con el gancho useTranslation o el HOC withTranslation.
¿Está intentando generar una exportación HTML estática ejecutando next export
y recibe este error?
Error: la compatibilidad con i18n no es compatible con la próxima exportación. Consulte aquí para obtener más información sobre la implementación: https://nextjs.org/docs/deployment
Pero hay una manera de solucionar este problema con la ayuda del detector de siguiente idioma. Consulte esta publicación de blog y este proyecto de ejemplo.
Tiene varias formas de utilizar la función t en su componente secundario:
t
a través de accesorios a los niñosuseTranslation
, como en este ejemplo:siguiente-i18next/examples/simple/components/Footer.tsx
Línea 6 en e6b5085
withTranslation
Y, en general, siempre debe asegurarse de que serverSideTranslations contenga todos los espacios de nombres que necesita en el árbol.
Gracias a estas maravillosas personas (tecla emoji):
Rob Capellini | Alejandro Kachkaev ? ? | Mathias Wobbe ? | Lucas Feliciano ? ? | ryan leung | Nathan Friemel ? | Isaac Hinman ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? |
Adriano Rayano ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? | Félix Mosheev ? | Sébastien Vanvelthem ? ? |
Este proyecto sigue la especificación de todos los contribuyentes. ¡Se aceptan aportes de cualquier tipo!
localización como servicio - locize.com
¿Necesitas una gestión de traducción? ¿Quieres editar tus traducciones con un editor InContext? ¡Utilice el original que le proporcionaron los mantenedores de i18next!
Al utilizar locize, respalda directamente el futuro de i18next y next-i18next.