Fácil i18n para next.js +10
Siguiente complemento + API I18N
Nota
Estamos trabajando con la versión 3.0.0 de la siguiente traducción. En los últimos meses nos hemos centrado mucho en Brisa . Por lo tanto, ha pasado mucho tiempo desde el último lanzamiento, pero no hemos olvidado el próximo tradato. Estamos trabajando en una nueva versión que traerá muchas mejoras y nuevas características. Estamos muy emocionados de compartirlo con todos ustedes.

El objetivo principal de esta biblioteca es mantener las traducciones lo más simples posible en un entorno Next.js.
El próximo traductor tiene dos partes: API Next.JS Plugin + I18N.
Características

En el archivo de configuración, especifica cada página que las necesidades de los espacios de nombres:
i18n.json
{
"pages" : {
"*" : [ "common" ] ,
"/" : [ "home" ] ,
"/cart" : [ "cart" ] ,
"/content/[slug]" : [ "content" ] ,
"rgx:^/account" : [ "account" ]
}
// rest of config here...
}Lea aquí sobre cómo agregar los archivos JSON espaciales de nombres.
El próximo tradato asegura que cada página solo tenga sus espacios de nombres con el idioma actual. Entonces, si tenemos 100 locales, solo se cargará 1.
Para hacer esto, utilizamos un cargador web que carga los archivos de traducción necesarios dentro de los métodos Next.js ( GetStaticProps , GetServerSideProps o GetInitialProps ). Si ya tiene uno de estos métodos en su página, el cargador webpack usará su propio método, pero los valores predeterminados que usará son:
getStaticProps . Este es el método predeterminado utilizado en la mayoría de las páginas , a menos que sea una página especificada en los siguientes dos puntos. Esto es para el rendimiento, por lo que los cálculos se realizan en el tiempo de compilación en lugar del tiempo de solicitud.getServerSideProps . Este es el método predeterminado para páginas dinámicas como [slug].js o [...catchall].js . Esto se debe a que para estas páginas es necesario definir los getStaticPaths y no hay conocimiento de cómo deberían ser las babosas para cada localidad. Del mismo modo, ¿cómo es de forma predeterminada, solo que escribe GetstaticPaths, entonces ya usará GetStaticProps para cargar las traducciones?getInitialProps . Este es el método predeterminado para estas páginas que usan un HOC . Esto es para evitar conflictos porque HOC podría sobrescribir un getInitialProps . Todo este proceso es transparente , por lo que en sus páginas puede consumir directamente el gancho useTranslation para usar los espacios de nombres, y no necesita hacer nada más.
Si por alguna razón usa un getInitialProps en su archivo _app.js , las traducciones solo se cargarán en su getInitialProps desde _app.js . Recomendamos que por razones de optimización no use este enfoque a menos que sea absolutamente necesario.
yarn add next-translate El next-translate-plugin es una herramienta que permite a los desarrolladores manejar de manera eficiente las traducciones en base a página por página durante el proceso de compilación. Es distinto del paquete next-translate , que permite a los desarrolladores acceder a las traducciones en el código donde se necesita. El complemento funciona analizando todas las páginas, buscando las traducciones y reescribiendo el archivo de página agregando las traducciones a él. Esto hace que el complemento sea una solución más eficiente y flexible para manejar traducciones dentro de una aplicación Next.js. Se recomienda instalar el complemento como un Devdependency.
yarn add next-translate-plugin -DEn su archivo next.config.js :
const nextTranslate = require ( 'next-translate-plugin' )
module . exports = nextTranslate ( ) O si ya tiene el archivo next.config.js y desea mantener los cambios en él, pase el objeto de configuración al nextTranslate() . Por ejemplo, para Webpack, podría hacerlo así:
const nextTranslate = require ( 'next-translate-plugin' )
module . exports = nextTranslate ( {
webpack : ( config , { isServer , webpack } ) => {
return config ;
}
} ) Agregue un archivo de configuración i18n.json (o i18n.js con module.exports ) en la raíz del proyecto. Cada página debe tener sus espacios de nombres. Eche un vistazo a la sección de configuración para obtener más detalles.
{
"locales" : [ " en " , " ca " , " es " ],
"defaultLocale" : " en " ,
"pages" : {
"*" : [ " common " ],
"/" : [ " home " , " example " ],
"/about" : [ " about " ]
}
}En el archivo de configuración puede usar tanto la configuración que especificamos aquí como las propias características sobre la internacionalización de Next.js 10.
De manera predeterminada, los espacios de nombres se especifican en el directorio de /locales root de esta manera:
/Locos
.
├── ca
│ ├── common.json
│ └── home.json
├── en
│ ├── common.json
│ └── home.json
└── es
├── common.json
└── home.json Cada nombre de archivo coincide con el espacio de nombres especificado en la propiedad de configuración pages , mientras que cada contenido del archivo debe ser similar a este:
{
"title" : " Hello world " ,
"variable-example" : " Using a variable {{count}} "
}Sin embargo, puede usar otro destino para guardar sus archivos de espacios de nombres utilizando la propiedad de configuración de LoadLocaleFrom:
i18n.js
{
// ...rest of config
"loadLocaleFrom" : ( lang , ns ) =>
// You can use a dynamic import, fetch, whatever. You should
// return a Promise with the JSON file.
import ( `./myTranslationsFiles/ ${ lang } / ${ ns } .json` ) . then ( ( m ) => m . default ) ,
}Luego, use las traducciones en la página y sus componentes:
páginas/ejemplo.js
import useTranslation from 'next-translate/useTranslation'
export default function ExamplePage ( ) {
const { t , lang } = useTranslation ( 'common' )
const example = t ( 'variable-example' , { count : 42 } )
return < div > { example } </ div > // <div>Using a variable 42</div>
}Puede consumir las traducciones directamente en sus páginas, no tiene que preocuparse por cargar los archivos de espacios de nombres manualmente en cada página. El complemento del próximo traductor carga solo los espacios de nombres que la página necesita y solo con el idioma actual.
En el archivo de configuración puede usar tanto la configuración que especificamos aquí como las propias características sobre la internacionalización de Next.js 10.
| Opción | Descripción | Tipo | Por defecto |
|---|---|---|---|
defaultLocale | ISO de la ubicación predeterminada ("EN" como predeterminada). | string | "en" |
locales | Una matriz con todos los idiomas para usar en el proyecto. | string[] | [] |
loadLocaleFrom | Cambie la forma en que carga los espacios de nombres. | function que devuelve una Promise con el JSON . | Por defecto, está cargando los espacios de nombres desde el directorio raíz de los locales . |
pages | Un objeto que define los espacios de nombres utilizados en cada página. Ejemplo de objeto: {"/": ["home", "example"]} . Para agregar espacios de nombres a todas las páginas, debe usar la clave "*" , ex: {"*": ["common"]} . También es posible usar regex usando rgx: en el frente: {"rgx:/form$": ["form"]} . También puede usar una función en lugar de una matriz, para proporcionar algunos espacios de nombres dependiendo de algunas reglas, ex: { "/": ({ req, query }) => query.type === 'example' ? ['example'] : []} | Object<string[] or function> | {} |
logger | Funciona para registrar las teclas faltantes en el desarrollo y la producción. Si está utilizando i18n.json como archivo de configuración, debe cambiarlo a i18n.js | function | Por defecto, el registrador es una función que realiza una console.warn Warn solo en el desarrollo. |
loggerEnvironment | Cadena para definir si el registrador debe ejecutarse en el navegador, en el nodo o ambos | "node" | "browser" | "both" | "browser" |
logBuild | Cada página tiene un registro que indica: espacios de nombres, lenguaje y método actuales utilizados para cargar los espacios de nombres. Con esto puedes deshabilitarlo. | Boolean | true |
loader | Si desea deshabilitar el cargador webpack y cargar manualmente los espacios de nombres en cada página, le brindamos la oportunidad de hacerlo deshabilitando esta opción. | Boolean | true |
interpolation | Cambie el delimitador que se usa para la interpolación. | {prefix: string; suffix: string, formatter: function } | {prefix: '{{', suffix: '}}'} |
keySeparator | Cambie el separador que se usa para las teclas anidadas. Establezca en false para deshabilitar las teclas anidando en archivos de traducción JSON. Puede ser útil si desea usar el texto natural como teclas. | string | false | '.' |
nsSeparator | Char para dividir el espacio de nombres de la clave. Debe configurarlo en false si desea usar texto natural como teclas. | string | false | ':' |
defaultNS | Espacio de nombres predeterminado utilizado si no se pasa a useTranslation o en la clave de traducción. | string | undefined |
staticsHoc | Los hocs que tenemos en nuestra API (AppWithi18n), no usan estatales de Hoist-Non-react para no incluir más KB de los necesarios (valores estáticos diferentes a GetInitialProps en las páginas rara vez se usan) . Si tiene algún conflicto con las estadísticas, puede agregar Hoist-Non-React-Statics (o cualquier otra alternativa) aquí. Ver un ejemplo. | Function | null |
extensionsRgx | Cambie la regex utilizada por el cargador webpack para encontrar las páginas Next.js. | Regex | /.(tsx|ts|js|mjs|jsx)$/ |
revalidate | Si desea tener una revalidación predeterminada en cada página, le damos la oportunidad de hacerlo aprobando un número para revalidar. Todavía puede definir GetstaticProps en una página con una cantidad de revalidación diferente y anular esta anulación predeterminada. | Number | Si no lo define, de forma predeterminada, las páginas no tendrán revalidar. |
pagesInDir | Si ejecuta next ./my-app para cambiar dónde están sus páginas, puede definir aquí my-app/pages para que el próximo traducir pueda adivinar dónde están. | String | Si no lo define, de forma predeterminada, las páginas se buscarán en los lugares clásicos como pages y src/pages . |
localesToIgnore | Indique estos lugares para ignorar cuándo está prefijando la localidad predeterminada usando un middleware (en el siguiente +12, aprenda cómo hacerlo) | Array<string> | ['default'] |
allowEmptyStrings | Cambie cómo se deben manejar las cadenas vacías traducidas. Si se omite o pasa como verdadero, devuelve una cadena vacía. Si se pasa como falso, devuelve el nombre clave en sí mismo (incluido NS). | Boolean | true |
Tamaño : ~ 150b?
Este gancho es la forma recomendada de usar traducciones en sus páginas / componentes.
Ejemplo:
import React from 'react'
import useTranslation from 'next-translate/useTranslation'
export default function Description ( ) {
const { t , lang } = useTranslation ( 'ns1' ) // default namespace (optional)
const title = t ( 'title' )
const titleFromOtherNamespace = t ( 'ns2:title' )
const description = t `description` // also works as template string
const example = t ( 'ns2:example' , { count : 3 } ) // and with query params
const exampleDefault = t ( 'ns:example' , { count : 3 } , { default : "The count is: {{count}}." } ) // and with default translation
return (
< >
< h1 > { title } </ h1 >
< p > { description } </ p >
< p > { example } </ p >
< >
)
} La función t :
i18nKey . Similar a useTranslation pero sin ser un gancho. Este ayudante solo funciona en la aplicación Dir .
const { t , lang } = createTranslation ( 'ns1' ) // default namespace (optional)
const title = t ( 'title' )Tamaño : ~ 560b?
Es una alternativa al gancho useTranslation , pero en un hoc para estos componentes que no son funcionales. (No se recomienda, es mejor usar el gancho useTranslation ) .
withTranslation hoc devuelve un componente con un accesorio adicional llamado i18n (objeto {t: función, lang: string}).
Ejemplo:
import React from 'react'
import withTranslation from 'next-translate/withTranslation'
class Description extends React . Component {
render ( ) {
const { t , lang } = this . props . i18n
const description = t ( 'common:description' )
return < p > { description } </ p >
}
}
export default withTranslation ( NoFunctionalComponent ) Similar a useTranslation("common") puede llamar withTranslation con el segundo parámetro que define un espacio de nombres predeterminado para usar:
export default withTranslation(NoFunctionalComponent, "common")
Tamaño : ~ 1.4kb?
A veces necesitamos hacer algunas traducciones con HTML dentro del texto (negrita, enlaces, etc.), el componente Trans es exactamente lo que necesita para esto. Recomendamos utilizar este componente solo en este caso, para otros casos, recomendamos encarecidamente el uso del gancho useTranslation .
Ejemplo:
// The defined dictionary entry is like:
// "example": "<0>The number is <1>{{count}}</1></0>",
< Trans
i18nKey = "common:example"
components = { [ < Component /> , < b className = "red" /> ] }
values = { { count : 42 } }
/> O el uso components como un objeto:
// The defined dictionary entry is like:
// "example": "<component>The number is <b>{{count}}</b></component>",
< Trans
i18nKey = "common:example"
components = { {
component : < Component /> ,
b : < b className = "red" /> ,
} }
values = { { count : 42 } }
defaultTrans = "<component>The number is <b>{{count}}</b></component>"
/>i18nKey - cadena - clave de la entrada i18n (espacio de nombres: clave)components - Array | Objeto: en caso de matriz, cada índice corresponde a la etiqueta definida <0> / <1> . En el caso de objeto, cada clave corresponde a la etiqueta definida <example> .values - objeto - parámetros de consultafallback - Cadena | cadena [] - opcional. Fallback i18Nkey si el i18nkey no coincide.defaultTrans - String - Traducción predeterminada para la clave. Si se usan claves de retroceso, se usará solo después de agotar todas las noches.ns - espacio de nombres para usar cuando ninguno está incrustado en i18nKeyreturnObjects - Boolean - Obtén parte del JSON con todas las traducciones. Ver más. En los casos en que requerimos la funcionalidad del componente Trans , pero necesitamos interpolar una cadena , en lugar de la salida de la función t(props.i18nKey) , también hay un componente TransText , que toma un text en lugar de i18nKey .
text - String - La cadena que (opcionalmente) contiene etiquetas que requieren interpolacióncomponents - Array | Objeto: esto se comporta exactamente igual que Trans (ver arriba). Esto es especialmente útil cuando se mapea sobre la salida de un t() con returnObjects: true :
// The defined dictionary entry is like:
// "content-list": ["List of <link>things</link>", "with <em>tags</em>"]
const contentList = t ( 'someNamespace:content-list' , { } , { returnObjects : true } ) ;
{ contentList . map ( ( listItem : string ) => (
< TransText
text = { listItem }
components = { {
link : < a href = "some-url" /> ,
em : < em /> ,
} }
/>
) }Tamaño : ~ 1.5kb?
El componente DynamicNamespaces es útil para cargar espacios de nombres dinámicos, por ejemplo, en modales.
Ejemplo:
import React from 'react'
import Trans from 'next-translate/Trans'
import DynamicNamespaces from 'next-translate/DynamicNamespaces'
export default function ExampleWithDynamicNamespace ( ) {
return (
< DynamicNamespaces namespaces = { [ 'dynamic' ] } fallback = "Loading..." >
{ /* ALSO IS POSSIBLE TO USE NAMESPACES FROM THE PAGE */ }
< h1 >
< Trans i18nKey = "common:title" />
</ h1 >
{ /* USING DYNAMIC NAMESPACE */ }
< Trans i18nKey = "dynamic:example-of-dynamic-translation" />
</ DynamicNamespaces >
)
} Recuerde que el espacio de nombres ['dynamic'] no debe enumerarse en la configuración pages :
pages: {
'/my-page' : [ 'common' ] , // only common namespace
}namespaces - String [] - Lista de espacios de nombres dinámicos para descargar - requerido .fallback - Reactnode - Fallback para mostrar mientras que los espacios de nombres se están cargando. - Opcional .dynamic - Función - Por defecto, utiliza LoadLocaleFrom en la configuración para cargar los espacios de nombres, pero puede especificar otro destino. - Opcional .Tamaño : ~ 1.3kb?
Función asincrónica para cargar la función t fuera de los componentes / páginas. Funciona tanto en el lado del servidor como en el lado del cliente.
A diferencia del gancho usetranslation, podemos usar aquí en cualquier espacio de nombres, no tiene que ser un espacio de nombres definido en la configuración de "páginas". Descarga el espacio de nombres indicado como un parámetro en el tiempo de ejecución.
Puede cargar múltiples espacios de nombres dando una matriz como parámetro, en este caso, el espacio de nombres predeterminado será el FIST.
Ejemplo dentro de getStaticProps :
import getT from 'next-translate/getT'
// ...
export async function getStaticProps ( { locale } ) {
const t = await getT ( locale , 'common' )
const title = t ( 'title' )
return { props : { title } }
}Ejemplo dentro de la ruta API:
import getT from 'next-translate/getT'
export default async function handler ( req , res ) {
const t = await getT ( req . query . __nextLocale , 'common' )
const title = t ( 'title' )
res . statusCode = 200
res . setHeader ( 'Content-Type' , 'application/json' )
res . end ( JSON . stringify ( { title } ) )
}Ejemplo de carga de múltiples espacios de nombres:
import getT from 'next-translate/getT'
export default async function handler ( req , res ) {
const t = await getT ( req . query . __nextLocale , [ 'common' , 'errors' ] )
const title = t ( 'title' ) // The default namespace is the first one.
const errorMessage = t ( 'errors:app_error' ) // The default namespace is the first one.
res . statusCode = 200
res . setHeader ( 'Content-Type' , 'application/json' )
res . end ( JSON . stringify ( { title } ) )
}Tamaño : ~ 3kb?
El I18nProvider es un proveedor de contexto utilizado internamente por el próximo traducido para proporcionar el LANG actual y los espacios de nombres de la página. Entonces tal vez nunca necesitarás esto .
Sin embargo, está expuesto a la API porque puede ser útil en algunos casos. Por ejemplo, para usar traducciones de varios idiomas en una página.
El I18nProvider está acumulando los espacios de nombres, por lo que puede cambiar el nombre de los nuevos para mantener los viejos.
import React from 'react'
import I18nProvider from 'next-translate/I18nProvider'
import useTranslation from 'next-translate/useTranslation'
// Import English common.json
import commonEN from '../../locales/en/common.json'
function PageContent ( ) {
const { t , lang } = useTranslation ( )
console . log ( lang ) // -> current language
return (
< div >
< p > { t ( 'common:example' ) /* Current language */ } </ p >
< p > { t ( 'commonEN:example' ) /* Force English */ } </ p >
</ div >
)
}
export default function Page ( ) {
const { lang } = useTranslation ( )
return (
< I18nProvider lang = { lang } namespaces = { { commonEN } } >
< PageContent />
</ I18nProvider >
)
}Tamaño : ~ 3.7kb?
El appWithI18n es utilizado internamente por el siguiente tradato. Entonces tal vez nunca necesitarás esto . Sin embargo, lo exponemos en la API en caso de que deshabilite la opción del cargador webpack y decidamos cargar los espacios de nombres manualmente.
Si no desea usar el Webpack Loader, debe poner esto en su archivo _app.js (y crear el archivo _app.js si no lo tiene).
Ejemplo:
_app.js
import appWithI18n from 'next-translate/appWithI18n'
import i18nConfig from '../i18n'
function MyApp ( { Component , pageProps } ) {
return < Component { ... pageProps } />
}
// Wrapping your _app.js
export default appWithI18n ( MyApp , {
... i18nConfig ,
// Set to false if you want to load all the namespaces on _app.js getInitialProps
skipInitialProps : true ,
} ) Si skipInitialProps=true , también debe usar el ayudante LoadNames Spaces para cargar manualmente los espacios de nombres en cada página.
Tamaño : ~ 1.9kb?
loadNamespaces es utilizado internamente por el próximo traduco. Entonces tal vez nunca necesitarás esto . Sin embargo, lo exponemos en la API en caso de que deshabilite la opción del cargador webpack y decidamos cargar los espacios de nombres manualmente.
Para cargar los espacios de nombres, debe devolver en sus páginas los accesorios que proporciona el ayudante.
import loadNamespaces from 'next-translate/loadNamespaces'
export function getStaticProps ( { locale } ) {
return {
props : {
... ( await loadNamespaces ( { locale , pathname : '/about' } ) ) ,
}
}
} Para funcionar bien, es necesario que su _app.js se envuelva con la AppWithi18n. Además, la propiedad loadLocaleFrom Configuration es obligatoria para definirla.
Apoyamos 6 formas plurales (tomadas de la página de plurals CLDR) agregando a la clave este sufijo (o anidándolo debajo de la clave sin _ prefijo):
_zero_one (singular)_two (dual)_few (paucal)_many (también utilizado para fracciones si tienen una clase separada)_other (requerido - forma plural general - también se usa si el idioma solo tiene una sola forma)Vea más información sobre Plurals aquí .
Solo se requiere el último, _other , porque es la única forma plural común utilizada en todos los lugares.
Todas las demás formas plurales dependen de la ubicación. Por ejemplo, el inglés solo tiene dos: _one y _other (1 gato vs. 2 gatos). Algunos idiomas tienen más, como el ruso y el árabe.
Además, también admitimos una coincidencia exacta especificando el número ( _0 , _999 ) y esto funciona para todos los lugares. Aquí hay un ejemplo:
Código:
// **Note**: Only works if the name of the variable is {{count}}.
t ( 'cart-message' , { count } )Espacio de nombres:
{
"cart-message_0" : "The cart is empty" , // when count === 0
"cart-message_one" : "The cart has only {{count}} product" , // singular
"cart-message_other" : "The cart has {{count}} products" , // plural
"cart-message_999" : "The cart is full" , // when count === 999
}o
{
"cart-message" : {
"0" : "The cart is empty" , // when count === 0
"one" : "The cart has only {{count}} product" , // singular
"other" : "The cart has {{count}} products" , // plural
"999" : "The cart is full" , // when count === 999
}
}Intl.PluralRules API solo está disponible para los navegadores modernos , si desea usarlo en navegadores heredados, debe agregar un polifil.
Puede definir HTML dentro de la traducción de esta manera:
{
"example-with-html" : " <0>This is an example <1>using HTML</1> inside the translation</0> "
}Ejemplo:
import Trans from 'next-translate/Trans'
// ...
const Component = ( props ) => < p { ... props } />
// ...
< Trans
i18nKey = "namespace:example-with-html"
components = { [ < Component /> , < b className = "red" /> ] }
/ >Resultado renderizado:
< p > This is an example < b class =" red " > using HTML </ b > inside the translation </ p > Cada matriz de índice de components corresponde con <index></index> de la definición.
En la matriz components , no es necesario pasar a los hijos de cada elemento. Los niños serán calculados.
En el espacio de nombres, es posible definir claves anidadas como esta:
{
"nested-example" : {
"very-nested" : {
"nested" : " Nested example! "
}
}
}Para usarlo, debe usar "." Como separador de identificación:
t `namespace:nested-example.very-nested.nested`También es posible usar como matriz:
{
"array-example" : [
{ "example" : " Example {{count}} " },
{ "another-example" : " Another example {{count}} " }
]
} Y obtenga todas las traducciones de matriz con la opción returnObjects :
t ( 'namespace:array-example' , { count : 1 } , { returnObjects : true } )
/*
[
{ "example": "Example 1" },
{ "another-example": "Another example 1" }
]
*/ También es posible obtener todas las traducciones utilizando el KeySparator como la clave, el valor predeterminado es '.' :
t ( 'namespace:.' , { count : 1 } , { returnObjects : true } )
/*
{
"array-example": [
{ "example": "Example 1" },
{ "another-example": "Another example 1" }
]
}
*/ Si no existe una traducción, puede definir Fallbacks ( string|string[] ) para buscar otras traducciones:
const { t } = useTranslation ( )
const textOrFallback = t (
'ns:text' ,
{ count : 1 } ,
{
fallback : 'ns:fallback' ,
}
)Lista de respaldos:
const { t } = useTranslation ( )
const textOrFallback = t (
'ns:text' ,
{ count : 42 } ,
{
fallback : [ 'ns:fallback1' , 'ns:fallback2' ] ,
}
)En el componente trans:
< Trans
i18nKey = "ns:example"
components = { [ < Component /> , < b className = "red" /> ] }
values = { { count : 42 } }
fallback = { [ 'ns:fallback1' , 'ns:fallback2' ] } // or string with just 1 fallback
/> Puede formatear parámetros utilizando la función de configuración interpolation.format .
En i18n.js :
const formatters = {
es : new Intl . NumberFormat ( "es-ES" ) ,
en : new Intl . NumberFormat ( "en-EN" ) ,
}
return {
// ...
interpolation : {
format : ( value , format , lang ) => {
if ( format === 'number' ) return formatters [ lang ] . format ( value )
return value
}
}
}En el espacio de nombres en inglés:
{
"example" : " The number is {{count, number}} "
}En el espacio de nombres español:
{
"example" : " El número es {{count, number}} "
}Usando:
t ( 'example' , { count : 33.5 } )Devoluciones:
The number is 33.5El número es 33,5 Para cambiar el idioma actual, puede usar la navegación Next.js (enlace y enrutador) que pasa el accesorio locale .
Un ejemplo de un posible componente ChangeLanguage utilizando el gancho useRouter de Next.js :
import React from 'react'
import Link from 'next/link'
import useTranslation from 'next-translate/useTranslation'
import i18nConfig from '../i18n.json'
const { locales } = i18nConfig
export default function ChangeLanguage ( ) {
const { t , lang } = useTranslation ( )
return locales . map ( ( lng ) => {
if ( lng === lang ) return null
return (
< Link href = "/" locale = { lng } key = { lng } >
{ t ( `layout:language-name- ${ lng } ` ) }
</ Link >
)
} )
} También puede usar setLanguage para cambiar el idioma mientras mantiene la misma página.
import React from 'react'
import setLanguage from 'next-translate/setLanguage'
export default function ChangeLanguage ( ) {
return (
< button onClick = { async ( ) => await setLanguage ( 'en' ) } > EN </ button >
)
} Otra forma de acceder a la lista locales para cambiar el idioma es usar el Next.js router Se puede acceder a la lista locales utilizando el gancho de usuarios Next.js.
Puede establecer una cookie llamada NEXT_LOCALE con el idioma definido por el usuario como valor, de esta manera se puede forzar una ubicación.
Ejemplo de gancho:
import { useRouter } from 'next/router'
// ...
function usePersistLocaleCookie ( ) {
const { locale , defaultLocale } = useRouter ( )
useEffect ( persistLocaleCookie , [ locale , defaultLocale ] )
function persistLocaleCookie ( ) {
if ( locale !== defaultLocale ) {
const date = new Date ( )
const expireMs = 100 * 24 * 60 * 60 * 1000 // 100 days
date . setTime ( date . getTime ( ) + expireMs )
document . cookie = `NEXT_LOCALE= ${ locale } ;expires= ${ date . toUTCString ( ) } ;path=/`
}
}
} En algunos casos, cuando la página está en el idioma actual, es posible que desee hacer algunas excepciones que muestren algún texto en otro idioma.
En este caso, puede lograr esto utilizando el I18nProvider .
Aprende a hacerlo aquí.
El siguiente traducir utiliza por defecto el directorio de trabajo actual del proceso node.js ( process.cwd() ).
Si quieres cambiarlo, puedes usar:
NEXT_TRANSLATE_PATH . Admite la ruta relativa y absolutaprocess.chdir(PATH_TO_NEXT_TRANSLATE) para mover el process.cwd() Cuando se trata de componentes del servidor y componentes del cliente, puede ser un desafío cargar lo mismo en diferentes páginas. Para simplificar este proceso, hemos extraído toda la complejidad utilizando el next-translate-plugin .
Si está interesado en obtener más información sobre cómo funciona el próximo tradato con el nuevo paradigma de la aplicación Next.js 13, consulte este artículo para obtener una explicación detallada.
Si usa la carpeta "APP" en lugar de la carpeta "Páginas", el next-translate-plugin detectará automáticamente el cambio, y no necesitará tocar ninguna de las próximas configuraciones de translato. La única diferencia es que la propiedad de configuración de "páginas" hará referencia a las páginas ubicadas dentro de la carpeta "Aplicación".
i18n.js
module . exports = {
locales : [ 'en' , 'ca' , 'es' ] ,
defaultLocale : 'en' ,
pages : {
'*' : [ 'common' ] ,
'/' : [ 'home' ] , // app/page.tsx
'/second-page' : [ 'home' ] , // app/second-page/page.tsx
} ,
} Simplemente cambiando la carpeta "Páginas" a "Aplicación", puede consumir traducciones dentro de sus páginas utilizando el gancho useTranslation o el componente Trans . Todavía verá el registro (si está habilitado) para saber qué espacios de nombres se cargan en cada página, y todo lo demás debería ser el mismo.
? Página del servidor/componente (+0kb): app/page.js :
import useTranslation from 'next-translate/useTranslation'
export default function HomePage ( ) {
const { t , lang } = useTranslation ( 'home' )
return < h1 > { t ( 'title' ) } </ h1 >
} ? ️ Página/componente del cliente (+498b): app/checkout/page.js
"use client"
import useTranslation from 'next-translate/useTranslation'
export default function CheckoutPage ( ) {
const { t , lang } = useTranslation ( 'checkout' )
return < h1 > { t ( 'title' ) } </ h1 >
} Next.js 10 introdujo el soporte de enrutamiento i18n, lo que permite que las páginas se rendericen navegando a /es/page-name , donde se accedió a las pages/page-name.js utilizando el gancho useRouter para obtener la locale .
Sin embargo, dado que las páginas se han movido de las pages Dir a la aplicación Dir , este enrutamiento I18N ya no funciona correctamente .
En el próximo traduco, hemos elegido no volver a implementar esta funcionalidad, ya que nuestro objetivo es ser una biblioteca para traducir páginas, en lugar de enrutarlas. Esperamos que en el futuro, esta característica se implementará en el directorio app .
Recomendamos lo siguiente:
[lang] al primer nivel. Es decir, todas sus páginas estarán dentro /app/[lang] .i18n.(js|json) para contener el /[lang] al principio. module.exports = {
locales: ['en', 'ca', 'es'],
defaultLocale: 'en',
pages: {
'*': ['common'],
- '/': ['home'],
+ '/[lang]': ['home'],
- '/second-page': ['home'],
+ '/[lang]/second-page': ['home'],
},
} En el nivel siguiente de translato ya detectamos el idioma automáticamente según searchParams.get('lang') y params.lang . Por lo tanto , no necesita configurarlo para cada página , puede usar next-translate como normal dentro de las páginas/componentes del servidor/cliente:
import useTranslation from 'next-translate/useTranslation'
import Trans from 'next-translate/Trans'
export default function Page ( ) {
const { t , lang } = useTranslation ( 'common' )
return (
< >
< h1 > { t `title` } </ h1 >
< Trans i18nKey = "common:another-text" components = { [ < b /> ] } />
</ >
)
} Hay una demostración de next-translate en el próximo Repo: JS:
Para usarlo:
npx create-next-app --example with-next-translate with-next-translate-app
# or
yarn create next-app --example with-next-translate with-next-translate-appEsta demostración está en este repositorio:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:basicSimilar a la demostración básica pero con algunos extras: TypeScript, Webpack 5, MDX, con _App.js en la parte superior, páginas ubicadas en la carpeta SRC/Pages, cargando locales de SRC/traducciones con una estructura diferente.
Esta demostración está en este repositorio:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:complex Similar a la demostración compleja pero con algunos extra: en lugar de la carpeta pages , estamos usando la carpeta de aplicaciones Next.js +13 con el nuevo sistema de diseños.
Esta demostración está en este repositorio:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:with-app-directorySimilar al ejemplo básico, pero cargando los espacios de nombres de la página, desactivando manualmente el cargador webpack en el archivo de configuración i18n.json.
No recomendamos que se use de esta manera. Sin embargo, le damos la oportunidad a cualquiera que lo haga si no se siente cómodo con nuestro Webpack Loader.
Esta demostración está en este repositorio:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:without-loader Gracias a estas maravillosas personas (Key Emoji):
Aral Roca Gómez ? | Vincent Ducorps | Björn rave | Justin | Polla ? | Ademílson F. Tonato | Faul |
bickmaev5 | Pierre Grimaud | Roman Minchyn | Egor | Darren | Giovanni Giordano | Eugene |
Andrew Chung | Thanh Minh | cuscurro | Patricio | Viertoy | Joey | Gurkerl83 |
Teemu Perämäki | Luis Serrano | J-SCHUMANN | Andre Hsu | Slevy85 | Bernd Artmüller | Rihards Ščeredins |
N4N5 | Rubén Moya | Tom Esterez | Dan Needham | Anunas de Bruno | Kaan Atakan | Romaín |
Arnau Jiménez | Edwin Veldhuizen | DUC ONG VIET | Billel Helali | Wuif | Michał Bar | Wuif |
Marces Engel | Michał Bar | Arrastrar | Marces Engel | Vasco Silva | Vsevolod Volkov | Felix yan |
Muhammad Al Ziqri | Marcelo Oliveira | Zack Sunderland | Andrew hornos | dani | Mateusz Lesiak | Curetix |
Honza ? | Hardikbandhiya | Tim O. Peters | Li Ming | Fernando García Hernández | Hichem Fantar | Huseyin Onal |
Jesse Martin |
Este proyecto sigue la especificación de todos los contribuyentes. ¡Contribuciones de cualquier tipo bienvenido!