Самый простой способ перевести ваши приложения Next.js (с настройкой страниц) .
Если вы используете next-i18next (каталог страниц) в рабочей среде и хотите раскрыть некоторые сверхспособности, вы можете просмотреть эту публикацию в блоге.
Если вы используете Next.js 13/14 с каталогом приложений, нет необходимости в next-i18next, вы можете напрямую использовать i18next и response-i18next, как описано в этом сообщении блога.
Хотя Next.js напрямую обеспечивает интернациональную маршрутизацию, он не занимается никаким управлением содержимым перевода или самой функциональностью перевода. Все, что делает Next.js, — это синхронизирует ваши локали и URL-адреса.
В дополнение к этому next-i18next
предоставляет оставшуюся функциональность — управление содержимым перевода и компоненты/хуки для перевода ваших компонентов React — при этом полностью поддерживая SSG/SSR, несколько пространств имен, разделение кода и т. д.
В то время как next-i18next
использует i18next и React-i18next под капотом, пользователям next-i18next
просто нужно включить свой контент перевода в виде файлов JSON и не беспокоиться ни о чем другом.
Живая демо-версия доступна здесь. Это демо-приложение является простым примером — ни больше, ни меньше.
Легко настроить, просто использовать: установка занимает всего несколько шагов, а настройка проста.
Никаких других требований: next-i18next
упрощает интернационализацию вашего приложения Next.js без дополнительных зависимостей.
Готовность к производству: next-i18next
поддерживает передачу переводов и параметров конфигурации на страницы в качестве реквизита с поддержкой SSG/SSR.
Ваш файл next-i18next.config.js
предоставит конфигурацию для next-i18next
. После настройки appWithTranslation
позволяет нам использовать функцию t
(перевод) в наших компонентах с помощью перехватчиков.
Затем мы добавляем serverSideTranslation
в getStaticProps или getServerSideProps (в зависимости от вашего случая) в наших компонентах уровня страницы.
Теперь наше приложение Next.js полностью переводимо!
yarn add next-i18next react-i18next i18next
Вам также необходимо иметь react
и next
установить.
По умолчанию next-i18next
ожидает, что ваши переводы будут организованы следующим образом:
.
└── public
└── locales
├── en
| └── common.json
└── de
└── common.json
Эту структуру также можно увидеть на простом примере.
Если вы хотите структурировать свои переводы/пространства имен по-своему, вам нужно будет передать измененные значения localePath
и localeStructure
в конфигурацию инициализации.
Сначала создайте файл next-i18next.config.js
в корне вашего проекта. Синтаксис вложенного объекта i18n
взят непосредственно из Next.js.
Это сообщает next-i18next
каковы ваши defaultLocale
и другие локали, чтобы он мог предварительно загружать переводы на сервер:
next-i18next.config.js
/** @type {import('next-i18next').UserConfig} */
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
}
Теперь создайте или измените файл next.config.js
, передав объект i18n
в файл next.config.js
, чтобы включить локализованную маршрутизацию URL-адресов:
next.config.js
const { i18n } = require ( './next-i18next.config' )
module . exports = {
i18n ,
}
next-i18next
экспортирует три функции, которые вам нужно будет использовать для перевода вашего проекта:
Это HOC, который оборачивает ваше _app
:
import { appWithTranslation } from 'next-i18next'
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp )
HOC appWithTranslation
в первую очередь отвечает за добавление I18nextProvider
.
Это асинхронная функция, которую вам необходимо включить в компоненты уровня страницы с помощью getStaticProps
или getServerSideProps
(в зависимости от вашего варианта использования):
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
} ,
}
}
Обратите внимание, что serverSideTranslations
необходимо импортировать из next-i18next/serverSideTranslations
— это отдельный модуль, содержащий код, специфичный для NodeJs.
Также обратите внимание, что serverSideTranslations
несовместим с getInitialProps
, поскольку он может выполняться только в серверной среде, тогда как getInitialProps
вызывается на стороне клиента при переходе между страницами.
HOC serverSideTranslations
в первую очередь отвечает за передачу переводов и параметров конфигурации на страницы в качестве реквизита — вам необходимо добавить его на любую страницу, имеющую переводы.
Это крючок, который вы фактически будете использовать для самого перевода. Хук useTranslation
взят из react-i18next
, но его необходимо импортировать напрямую из next-i18next
.
НЕ используйте экспорт useTranslation
из react-i18next
, а ТОЛЬКО используйте экспорт из next-i18next
!
import { useTranslation } from 'next-i18next'
export const Footer = ( ) => {
const { t } = useTranslation ( 'footer' )
return (
< footer >
< p > { t ( 'description' ) } < / p >
< / footer >
)
}
По умолчанию next-i18next
будет отправлять все ваши пространства имен клиенту при каждом первоначальном запросе. Это может быть подходящим подходом для небольших приложений с меньшим количеством контента, но многие приложения выиграют от разделения пространств имен на основе маршрута.
Для этого вы можете передать массив необходимых пространств имен для каждой страницы в serverSideTranslations
. Вы можете увидеть этот подход в example/simple/pages/index.tsx. Передача пустого массива необходимых пространств имен не приведет к отправке пространств имен.
Примечание. useTranslation
предоставляет пространства имен для компонента, в котором вы его используете. Однако serverSideTranslations
предоставляет все доступные пространства имен для всего дерева React и принадлежит на уровне страницы. Оба необходимы.
По умолчанию next-i18next
будет отправлять клиенту только активную локаль при каждом запросе. Это помогает уменьшить размер исходной полезной нагрузки, отправляемой клиенту. Однако в некоторых случаях во время выполнения могут потребоваться переводы и на другие языки. Например, при использовании getFixedT хука useTranslation
.
Чтобы изменить поведение и загрузить дополнительные локали, просто передайте массив локалей в качестве последнего аргумента 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'])),
},
};
}
В результате переводы как для no
, так и для en
locales будут всегда загружаться независимо от текущего языка.
Примечание. Дополнительный аргумент следует добавить на все страницы, использующие функцию
getFixedT
.
По умолчанию next-i18next
добавит defaultLocale
в качестве резервного варианта. Чтобы изменить это, вы можете установить fallbackLng
. Все значения, поддерживаемые i18next
( string
, array
, object
и function
), также поддерживаются next-i18next
.
Кроме того, для nonExplicitSupportedLngs
можно установить значение true
для поддержки всех вариантов языка без необходимости предоставления файлов JSON для каждого из них. Обратите внимание, что все варианты по-прежнему должны быть включены в locales
, чтобы включить маршрутизацию в next.js
Примечание.
fallbackLng
иnonExplicitSupportedLngs
можно использовать одновременно. Есть только одно исключение: вы не можете использовать функцию дляfallbackLng
еслиnonExplicitSupportedLngs
установленоtrue
.
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
}
Имейте в виду, что использование fallbackLng
и nonExplicitSupportedLngs
может легко увеличить первоначальный размер страницы.
К вашему сведению: установка для fallbackLng
значения false
НЕ приведет к сериализации вашего резервного языка (обычно defaultLocale
). Это уменьшит размер начальной загрузки страницы.
Если вам нужно изменить более сложные параметры конфигурации, вы можете передать их через next-i18next.config.js
. Например:
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
localePath :
typeof window === 'undefined'
? require ( 'path' ) . resolve ( './my-custom/path' )
: '/public/my-custom/path' ,
ns : [ 'common' ] ,
}
Некоторые плагины i18next
(которые вы можете передать в config.use
) несериализуемы, поскольку содержат функции и другие примитивы JavaScript.
Вы можете столкнуться с этим, если ваш вариант использования более продвинутый. Вы увидите, что Next.js выдает ошибку типа:
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.
Чтобы это исправить, вам нужно установить для config.serializeConfig
значение false
и вручную передать конфигурацию в 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
) ) ,
} ,
} )
При использовании на страницах, сгенерированных на стороне сервера, с getStaticPaths
и fallback: true
или fallback: 'blocking'
настройка по умолчанию, указанная выше, приведет к размонтированию и повторному монтированию приложения при каждой загрузке, что приведет к различным неблагоприятным последствиям, таким как вызов каждого useEffect(() => {...}, [])
дважды перехватываем и небольшое снижение производительности.
Это связано с тем, что для этих страниц Next.js выполняет первый рендеринг с пустыми serverSideProps
, а затем второй рендеринг с serverSideProps
, которые включают переводы next-i18next
. При настройке по умолчанию экземпляр i18n
изначально undefined
, когда serverSideProps
empty
, что приводит к размонтированию-перемонтированию.
Чтобы смягчить эту проблему, вы можете сделать следующее:
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
Это будет работать до тех пор, пока вы убедитесь, что в состоянии резервной страницы ваш клиентский код не пытается отобразить какой-либо перевод, поскольку в противном случае вы получите ошибку «несоответствие сервера и клиента» от Next.js (из-за тот факт, что сервер имеет фактический перевод в своем html, в то время как клиентский html имеет ключ перевода в том же месте).
Это нормально и нормально: вы все равно не должны показывать пользователю ключ перевода!
Начиная с версии 11.0.0 next-i18next также обеспечивает поддержку загрузки переводов на стороне клиента.
В некоторых случаях вам может потребоваться динамическая загрузка файла перевода без использования serverSideTranslations
. Это может быть особенно полезно для компонентов с отложенной загрузкой, которые не должны замедлять работу страниц.
Более подробную информацию об этом можно найти здесь.
Поскольку ресурсы загружаются один раз при запуске сервера, любые изменения, внесенные в файлы перевода JSON, находящиеся в разработке, не будут загружены до перезапуска сервера.
В рабочей среде это, как правило, не является проблемой, но при разработке вы можете захотеть видеть обновления файлов JSON перевода без необходимости каждый раз перезапускать сервер разработки. Для этого установите для параметра конфигурации reloadOnPrerender
значение true
.
Эта опция будет перезагружать ваши переводы при каждом вызове serverSideTranslations
(в getStaticProps
или getServerSideProps
). Если вы используете serverSideTranslations
в getServerSideProps
, рекомендуется отключить reloadOnPrerender
в производственных средах, чтобы избежать перезагрузки ресурсов при каждом вызове сервера.
Ключ | Значение по умолчанию | Примечание |
---|---|---|
defaultNS | 'common' | |
localePath | './public/locales' | Может быть функцией, см. примечание ниже. (также может быть нулевым, если опция ресурсов передается напрямую через конфигурацию, как здесь) |
localeExtension | 'json' | Игнорируется, если localePath является функцией. |
localeStructure | '{{lng}}/{{ns}}' | Игнорируется, если localePath является функцией. |
reloadOnPrerender | false | |
serializeConfig | true | |
use (для плагинов) | [] | |
onPreInitI18next | undefined | т.е. (i18n) => i18n.on('failedLoading', handleFailedLoading) |
localePath
как функция имеет форму (locale: string, namespace: string, missing: boolean) => string
возвращающая весь путь, включая имя файла и расширение. Если значение missing
, верните путь для параметра addPath
i18next-fs-backend
, если значение false, верните путь для параметра loadPath
. Дополнительную информацию можно найти в репозитории i18next-fs-backend
.
Если localePath является функцией, убедитесь, что вы также определили параметр ns, поскольку в этом случае на стороне сервера мы не сможем предварительно загрузить пространства имен.
Все остальные параметры i18next и параметры реакции-i18next также могут быть переданы.
Вы также можете передать resources
напрямую в сочетании с установкой localePath
значения null
.
По умолчанию i18next использует {{
в качестве префикса и }}
в качестве суффикса для интерполяции. Если вы хотите/нужно переопределить эти параметры интерполяции, вы также должны указать альтернативный параметр localeStructure
, соответствующий вашему пользовательскому префиксу и суффиксу.
Например, если вы хотите использовать {
и }
конфигурация будет выглядеть так:
{
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'nl' ] ,
} ,
interpolation : {
prefix : '{' ,
suffix : '}' ,
} ,
localeStructure : '{lng}/{ns}' ,
}
next-i18next.config.js
Если вы хотите изменить путь конфигурации по умолчанию, вы можете установить переменную среды I18NEXT_DEFAULT_CONFIG_PATH
.
Например, внутри файла .env
вы можете установить статический путь:
I18NEXT_DEFAULT_CONFIG_PATH=/path/to/project/apps/my-app/next-i18next.config.js
Или вы можете использовать трюк для динамического пути и установить следующее внутри 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 ,
...
} ;
Это означает, что файл конфигурации i18n будет находиться в том же каталоге, что и next.config.js
, и не имеет значения, где находится ваш текущий рабочий каталог. Это помогает, например, для nx
, когда у вас есть монорепо и вы запускаете приложение из корня проекта, но приложение находится в apps/{appName}
.
Примечание. Если ваша конфигурация next-i18next.config.js
находится не в том же каталоге, что и next.config.js
, вам необходимо скопировать ее вручную (или с помощью специального сценария).
Если вы планируете постепенно добавлять next-i18next в свой проект, мы рекомендуем вам передать ваш next-i18next.config
в appWithTranslation
, чтобы избежать каких-либо проблем.
т.е.
import nextI18nextConfig from '../../next-i18next.config' ;
//...
export default appWithTranslation ( MyApp , nextI18nextConfig ) ;
Дополнительную информацию см. в выпуске № 2259.
Некоторые бессерверные PaaS не смогут определить путь к вашим переводам и потребуют дополнительной настройки. Если у вас есть проблемы с файловой системой при использовании serverSideTranslations
, установите для config.localePath
значение path.resolve
. Пример можно найти здесь.
При развертывании Docker обратите внимание: если вы используете Dockerfile
из документации Next.js, не забудьте скопировать next.config.js
и next-i18next.config.js
в образ Docker.
COPY --from=builder /app/next.config.js ./next.config.js
COPY --from=builder /app/next-i18next.config.js ./next-i18next.config.js
Если вы решите использовать бэкэнд i18next, отличный от встроенного i18next-fs-backend, вам необходимо убедиться, что ресурсы перевода загружены, прежде чем вызывать функцию t
. Поскольку приостановка React еще не поддерживается для SSR, эту проблему можно решить двумя разными способами:
1) Предварительно загрузите пространства имен:
Установите параметр ns
, как в этом примере. Это обеспечит загрузку всех ресурсов перевода при инициализации.
2) Проверьте флаг готовности:
Если вы не можете или не хотите предоставлять массив ns
, вызовы функции t
приведут к загрузке пространств имен на лету. Это означает, что вам нужно будет обработать состояние «не готов», проверив ready === true
или props.tReady === true
. Если этого не сделать, ваши переводы будут отображаться до того, как они будут загружены, что приведет к вызову команды «сохранить отсутствующее», несмотря на то, что переводы действительно существуют (еще не загружены). Это можно сделать с помощью хука useTranslation или withTranslation HOC.
Вы пытаетесь создать статический экспорт HTML, выполняя next export
, и получаете эту ошибку?
Ошибка: поддержка i18n несовместима со следующим экспортом. Дополнительную информацию о развертывании см. здесь: https://nextjs.org/docs/deployment.
Но есть способ обойти это с помощью детектора следующего языка. Ознакомьтесь с этим сообщением в блоге и этим примером проекта.
У вас есть несколько способов использовать функцию t в дочернем компоненте:
t
через реквизит детямuseTranslation
, как в этом примере:следующий-i18next/примеры/простые/компоненты/Footer.tsx
Строка 6 в e6b5085
withTranslation
И вообще, вам всегда нужно быть уверенным, что serverSideTranslations содержит все нужные вам пространства имен в дереве.
Спасибо этим замечательным людям (ключ смайлика):
Роб Капеллини | Александр Качкаев ? ? | Матиас Вёббе ? | Лукас Фелисиано ? ? | Райан Люнг | Натан Фримель ? | Исаак Хинман ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? |
Адриано Райано ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? | Феликс Мошеев ? | Себастьян Ванвельтем ? ? |
Этот проект соответствует спецификации всех участников. Любой вклад приветствуется!
локализация как услуга - locize.com
Нужен менеджмент переводов? Хотите редактировать свои переводы с помощью редактора InContext? Используйте оригинал, предоставленный вам сопровождающими i18next!
Используя locize, вы напрямую поддерживаете будущее i18next и next-i18next.