A maneira mais fácil de traduzir seus aplicativos Next.js (com configuração de páginas) .
Se você estiver usando next-i18next (diretório de páginas) em produção e quiser liberar alguns superpoderes, dê uma olhada nesta postagem do blog.
Se você estiver usando Next.js 13/14 com diretório de aplicativos, não há necessidade de next-i18next, você pode usar i18next e react-i18next diretamente, conforme descrito nesta postagem do blog.
Embora Next.js forneça roteamento internacionalizado diretamente, ele não lida com nenhum gerenciamento de conteúdo de tradução ou com a própria funcionalidade de tradução. Tudo o que o Next.js faz é manter suas localidades e URLs sincronizados.
Para complementar isso, next-i18next
fornece a funcionalidade restante – gerenciamento de conteúdo de tradução e componentes/hooks para traduzir seus componentes React – ao mesmo tempo em que oferece suporte total a SSG/SSR, vários namespaces, divisão de códigos, etc.
Embora next-i18next
use i18next e react-i18next nos bastidores, os usuários do next-i18next
simplesmente precisam incluir seu conteúdo de tradução como arquivos JSON e não precisam se preocupar com muito mais.
Uma demonstração ao vivo está disponível aqui. Este aplicativo de demonstração é um exemplo simples - nada mais, nada menos.
Fácil de configurar, fácil de usar: a configuração leva apenas algumas etapas e a configuração é simples.
Nenhum outro requisito: next-i18next
simplifica a internacionalização do seu aplicativo Next.js sem dependências extras.
Pronto para produção: next-i18next
suporta a passagem de traduções e opções de configuração em páginas como acessórios com suporte SSG/SSR.
Seu arquivo next-i18next.config.js
fornecerá configuração para next-i18next
. Após a configuração, appWithTranslation
nos permite usar a função t
(translate) em nossos componentes por meio de ganchos.
Em seguida, adicionamos serverSideTranslation
a getStaticProps ou getServerSideProps (dependendo do seu caso) em nossos componentes de nível de página.
Agora nosso aplicativo Next.js é totalmente traduzível!
yarn add next-i18next react-i18next i18next
Você também precisa ter react
e next
instalado.
Por padrão, next-i18next
espera que suas traduções sejam organizadas da seguinte forma:
.
└── public
└── locales
├── en
| └── common.json
└── de
└── common.json
Essa estrutura também pode ser vista no exemplo simples.
Se você deseja estruturar suas traduções/namespaces de maneira personalizada, você precisará passar os valores localePath
e localeStructure
modificados para a configuração de inicialização.
Primeiro, crie um arquivo next-i18next.config.js
na raiz do seu projeto. A sintaxe do objeto i18n
aninhado vem diretamente de Next.js.
Isso informa next-i18next
qual é o seu defaultLocale
e outros locais, para que ele possa pré-carregar as traduções no servidor:
next-i18next.config.js
/** @type {import('next-i18next').UserConfig} */
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
}
Agora, crie ou modifique seu arquivo next.config.js
, passando o objeto i18n
para seu arquivo next.config.js
, para ativar o roteamento de URL localizado:
next.config.js
const { i18n } = require ( './next-i18next.config' )
module . exports = {
i18n ,
}
Existem três funções que next-i18next
exporta, que você precisará usar para traduzir seu projeto:
Este é um HOC que envolve seu _app
:
import { appWithTranslation } from 'next-i18next'
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp )
O appWithTranslation
HOC é o principal responsável por adicionar um I18nextProvider
.
Esta é uma função assíncrona que você precisa incluir nos componentes de nível de página, por meio de getStaticProps
ou getServerSideProps
(dependendo do seu 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
} ,
}
}
Observe que serverSideTranslations
deve ser importado de next-i18next/serverSideTranslations
– este é um módulo separado que contém código específico do NodeJs.
Além disso, observe que serverSideTranslations
não é compatível com getInitialProps
, pois só pode ser executado em um ambiente de servidor, enquanto getInitialProps
é chamado no lado do cliente ao navegar entre as páginas.
O serverSideTranslations
HOC é o principal responsável por passar traduções e opções de configuração nas páginas, como adereços – você precisa adicioná-lo a qualquer página que tenha traduções.
Este é o gancho que você realmente usará para fazer a tradução em si. O gancho useTranslation
vem de react-i18next
, mas precisa ser importado diretamente de next-i18next
.
NÃO use a exportação useTranslation
de react-i18next
, mas SOMENTE use aquela de next-i18next
!
import { useTranslation } from 'next-i18next'
export const Footer = ( ) => {
const { t } = useTranslation ( 'footer' )
return (
< footer >
< p > { t ( 'description' ) } < / p >
< / footer >
)
}
Por padrão, next-i18next
enviará todos os seus namespaces para o cliente em cada solicitação inicial. Essa pode ser uma abordagem apropriada para aplicativos menores com menos conteúdo, mas muitos aplicativos se beneficiarão da divisão de namespaces com base na rota.
Para fazer isso, você pode passar uma matriz de namespaces necessários para cada página em serverSideTranslations
. Você pode ver essa abordagem em exemplos/simple/pages/index.tsx. Passar uma matriz vazia de namespaces necessários não enviará nenhum namespace.
Nota: useTranslation
fornece namespaces para o componente em que você o usa. No entanto, serverSideTranslations
fornece o total de namespaces disponíveis para toda a árvore React e pertence ao nível da página. Ambos são obrigatórios.
Por padrão, next-i18next
enviará apenas a localidade ativa para o cliente em cada solicitação. Isso ajuda a reduzir o tamanho da carga inicial enviada ao cliente. No entanto, em alguns casos, também podem ser necessárias traduções para outros idiomas em tempo de execução. Por exemplo, ao usar getFixedT do gancho useTranslation
.
Para alterar o comportamento e carregar localidades extras, basta passar uma matriz de localidades como o último argumento para 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, as traduções para locais no
e en
serão sempre carregadas, independentemente do idioma atual.
Nota: O argumento extra deve ser adicionado a todas as páginas que usam a função
getFixedT
.
Por padrão, next-i18next
adicionará o defaultLocale
como substituto. Para mudar isso, você pode definir fallbackLng
. Todos os valores suportados por i18next
( string
, array
, object
e function
) também são suportados por next-i18next
.
Além disso, nonExplicitSupportedLngs
pode ser definido como true
para oferecer suporte a todas as variantes de uma linguagem, sem a necessidade de fornecer arquivos JSON para cada uma delas. Observe que todas as variantes ainda devem ser incluídas nas locales
para permitir o roteamento em next.js
.
Nota:
fallbackLng
enonExplicitSupportedLngs
podem ser usados ao mesmo tempo. Há apenas uma exceção: você não pode usar uma função parafallbackLng
quandononExplicitSupportedLngs
fortrue
,
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
}
Esteja ciente de que o uso de fallbackLng
e nonExplicitSupportedLngs
pode facilmente aumentar o tamanho inicial da página.
Para sua informação: Definir fallbackLng
como false
NÃO serializará sua linguagem substituta (geralmente defaultLocale
). Isso diminuirá o tamanho do carregamento inicial da página.
Se precisar modificar opções de configuração mais avançadas, você pode passá-las por meio de next-i18next.config.js
. Por exemplo:
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
localePath :
typeof window === 'undefined'
? require ( 'path' ) . resolve ( './my-custom/path' )
: '/public/my-custom/path' ,
ns : [ 'common' ] ,
}
Alguns plug-ins i18next
(que você pode passar para config.use
) não são serializáveis, pois contêm funções e outras primitivas JavaScript.
Você pode se deparar com isso se seu caso de uso for mais avançado. Você verá Next.js gerar um erro 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 corrigir isso, você precisará definir config.serializeConfig
como false
e passar manualmente sua configuração para 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
) ) ,
} ,
} )
Ao usar páginas geradas no lado do servidor com getStaticPaths
e fallback: true
ou fallback: 'blocking'
, a configuração padrão indicada acima fará com que o aplicativo seja desmontado e remontado a cada carregamento, causando várias consequências adversas, como chamar cada useEffect(() => {...}, [])
gancho duas vezes e leve degradação de desempenho.
Isso se deve ao fato de que, para essas páginas, Next.js faz uma primeira renderização com serverSideProps
vazio e depois uma segunda renderização com serverSideProps
que inclui as traduções next-i18next
. Com a configuração padrão, a instância i18n
é inicialmente undefined
quando serverSideProps
está empty
, causando a desmontagem-remontagem.
Para atenuar esse problema, você pode fazer o seguinte:
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
Isso funcionará contanto que você certifique-se de que, no estado da página substituta, seu código do lado do cliente não esteja tentando exibir nenhuma tradução, caso contrário você receberá um erro de "incompatibilidade servidor-cliente" do Next.js (devido ao fato de que o servidor possui uma tradução real em seu html enquanto o html do cliente possui a chave de tradução no mesmo local).
Isso é normal e correto: você não deveria exibir uma chave de tradução para o seu usuário de qualquer maneira!
Desde a v11.0.0, next-i18next também fornece suporte para carregamento de traduções no lado do cliente.
Em alguns casos de uso, você pode querer carregar um arquivo de tradução dinamicamente sem precisar usar serverSideTranslations
. Isso pode ser especialmente útil para componentes de carregamento lento que você não deseja que tornem as páginas mais lentas.
Mais informações sobre isso podem ser encontradas aqui.
Como os recursos são carregados uma vez quando o servidor é iniciado, quaisquer alterações feitas nos arquivos JSON de tradução em desenvolvimento não serão carregadas até que o servidor seja reiniciado.
Na produção, isso não tende a ser um problema, mas no desenvolvimento você pode querer ver atualizações nos arquivos JSON de tradução sem precisar reiniciar o servidor de desenvolvimento todas as vezes. Para fazer isso, defina a opção de configuração reloadOnPrerender
como true
.
Esta opção irá recarregar suas traduções sempre que serverSideTranslations
for chamado (em getStaticProps
ou getServerSideProps
). Se você estiver usando serverSideTranslations
em getServerSideProps
, é recomendado desabilitar reloadOnPrerender
em ambientes de produção para evitar o recarregamento de recursos em cada chamada do servidor.
Chave | Valor padrão | Observação |
---|---|---|
defaultNS | 'common' | |
localePath | './public/locales' | Pode ser uma função, veja a nota abaixo. (também pode ser nulo, se passar a opção de recursos diretamente via configuração, como aqui) |
localeExtension | 'json' | Ignorado se localePath for uma função. |
localeStructure | '{{lng}}/{{ns}}' | Ignorado se localePath for uma função. |
reloadOnPrerender | false | |
serializeConfig | true | |
use (para plug-ins) | [] | |
onPreInitI18next | undefined | ou seja, (i18n) => i18n.on('failedLoading', handleFailedLoading) |
localePath
como uma função tem o formato (locale: string, namespace: string, missing: boolean) => string
retornando o caminho inteiro, incluindo nome do arquivo e extensão. Quando missing
for verdadeiro, retorne o caminho para a opção addPath
de i18next-fs-backend
; quando for falso, retorne o caminho para a opção loadPath
. Mais informações no repositório i18next-fs-backend
.
Se localePath for uma função, certifique-se de definir também a opção ns, porque no lado do servidor não podemos pré-carregar os namespaces.
Todas as outras opções i18next e react-i18next também podem ser passadas.
Você também pode transmitir os resources
diretamente em combinação com a configuração localePath
como null
.
Por padrão, i18next usa {{
como prefixo e }}
como sufixo para interpolação. Se desejar/precisar substituir essas configurações de interpolação, você também deverá especificar uma configuração localeStructure
alternativa que corresponda ao seu prefixo e sufixo personalizados.
Por exemplo, se você quiser usar {
e }
a configuração ficaria assim:
{
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'nl' ] ,
} ,
interpolation : {
prefix : '{' ,
suffix : '}' ,
} ,
localeStructure : '{lng}/{ns}' ,
}
next-i18next.config.js
personalizado Se quiser alterar o caminho de configuração padrão, você pode definir a variável de ambiente I18NEXT_DEFAULT_CONFIG_PATH
.
Por exemplo, dentro do arquivo .env
você pode definir um caminho estático:
I18NEXT_DEFAULT_CONFIG_PATH=/path/to/project/apps/my-app/next-i18next.config.js
Ou você pode usar um truque para caminho dinâmico e definir o seguinte em 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 ,
...
} ;
Isso significa que o arquivo de configuração i18n estará no mesmo diretório que next.config.js
e não importa onde está seu diretório de trabalho atual. Isso ajuda, por exemplo, para nx
quando você tem monorepo e inicia seu aplicativo a partir da raiz do projeto, mas o aplicativo está em apps/{appName}
.
Aviso Se sua configuração next-i18next.config.js
não estiver no mesmo diretório que next.config.js
, você deverá copiá-la manualmente (ou por script personalizado).
Se você está planejando adicionar next-i18next de forma incremental ao seu projeto, recomendamos que você passe seu next-i18next.config
para appWithTranslation
para evitar problemas.
ou seja
import nextI18nextConfig from '../../next-i18next.config' ;
//...
export default appWithTranslation ( MyApp , nextI18nextConfig ) ;
Consulte a edição nº 2259 para obter mais informações.
Algumas PaaS sem servidor podem não conseguir localizar o caminho de suas traduções e exigir configuração adicional. Se você tiver problemas no sistema de arquivos usando serverSideTranslations
, defina config.localePath
para usar path.resolve
. Um exemplo pode ser encontrado aqui.
Para implantação do Docker, observe que se você usar o Dockerfile
dos documentos Next.js, não se esqueça de copiar next.config.js
e next-i18next.config.js
na imagem do Docker.
COPY --from=builder /app/next.config.js ./next.config.js
COPY --from=builder /app/next-i18next.config.js ./next-i18next.config.js
Se você optar por usar um back-end i18next diferente do back-end i18next-fs integrado, precisará garantir que os recursos de tradução sejam carregados antes de chamar a função t
. Como o suspense React ainda não é compatível com SSR, isso pode ser resolvido de 2 maneiras diferentes:
1) Pré-carregue os namespaces:
Defina a opção ns
, como neste exemplo. Isso garantirá que todos os recursos de tradução sejam carregados na inicialização.
2) Verifique o sinalizador de pronto:
Se você não puder ou não quiser fornecer o array ns
, as chamadas para a função t
farão com que os namespaces sejam carregados instantaneamente. Isso significa que você precisará lidar com o estado "não pronto" verificando ready === true
ou props.tReady === true
. Não fazer isso resultará na renderização de suas traduções antes de serem carregadas, o que fará com que "save missing" seja chamado apesar das traduções realmente existirem (ainda não carregadas). Isso pode ser feito com o gancho useTranslation ou com o HOC withTranslation.
Você está tentando gerar uma exportação HTML estática executando next export
e está recebendo este erro?
Erro: o suporte i18n não é compatível com a próxima exportação. Veja aqui para mais informações sobre implantação: https://nextjs.org/docs/deployment
Mas há uma maneira de contornar isso com a ajuda do detector de próximo idioma. Confira esta postagem do blog e este projeto de exemplo.
Você tem várias maneiras de usar a função t em seu componente filho:
t
por meio de adereços para as criançasuseTranslation
, como neste exemplo:next-i18next/examples/simple/components/Footer.tsx
Linha 6 em e6b5085
withTranslation
E, em geral, você sempre precisa ter certeza de que serverSideTranslations contém todos os namespaces necessários na árvore.
Os agradecimentos vão para essas pessoas maravilhosas (chave emoji):
Rob Capellini | Alexandre Kachkaev ? ? | Mathias Wøbbe ? | Lucas Feliciano ? ? | Ryan Leung | Nathan Friemel ? | Isaac Hinman ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? |
Adriano Raiano ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? | Félix Mosheev ? | Sébastien Vanvelthem ? ? |
Este projeto segue a especificação de todos os contribuidores. Contribuições de qualquer tipo são bem-vindas!
localização como serviço - locize.com
Precisando de um gerenciamento de tradução? Quer editar suas traduções com um Editor InContext? Use o original fornecido pelos mantenedores do i18next!
Com o uso do locize você apoia diretamente o futuro do i18next e do next-i18next.