Предложите свое приложение Next.js на нескольких языках с возвышенным next-i18next.

Исходный код этой статьи можно найти на GitLab.

Краткое вступление

Предложение вашего (Next.js) приложения на нескольких языках может показаться сложной задачей. Но в конце туннеля есть свет. next-i18next, с 75 000 загрузок в неделю, предлагает очень плавную интеграцию, а с небольшим количеством шаблонного кода все готово.

Давай посмотрим 🙂.

Настраивать

Запустите новый проект Next.js и добавьте зависимость:

$ yarn add next-i18next

Я также добавил великолепный пакет Luxon, который поможет нам с отображением даты (если вы хотите узнать больше о Luxon, ознакомьтесь с моей недавней статьей Знакомьтесь, Luxon, новый убийца Moment.js) и несколько semantic-ui пакетов для быстрого создания пользовательского интерфейса:

$ yarn add luxon semantic-ui-css semantic-ui-react

Что касается зависимости, мы в порядке. Давайте напишем немного шаблонного кода и сообщим нашему приложению Next.js, что мы собираемся его интернационализировать.

Код шаблона

Сначала мы создаем новый файл src/i18n.js и экспортируем экземпляр NextI18Next (извините, я не придумал это имя…):

Как видите, мы можем настроить некоторые детали о языках, которые мы собираемся использовать:

  • defaultLanguage: основной язык нашего приложения.
  • otherLanguages ​​: наши дополнительные языки
  • localeSubpaths: этот параметр определяет, как будет выглядеть путь нашего URL-адреса, когда пользователь переключится на дополнительный язык. Допустим, у нас есть страница about. Обычно и для нашего языка по умолчанию наш путь будет https://example.com/about. Но когда пользователь переключается на f.e. Испанский, путь станет https://example.com/es/about. Этот параметр контролирует это, вы можете настроить его, как хотите.
  • localePath: путь к нашим файлам перевода. Подробнее об этом скоро.

Еще один комментарий по поводу localeSubpaths заключается в том, что нам не нужно создавать эту структуру в нашем pages каталоге. Все может остаться, как вы привыкли, нам не нужно создавать папки для разных языков, такие как es и no:

Теперь переходим к нашему pages/_app.js файлу:

В этом файле мы обертываем наш компонент с помощью HOC (компонент высшего порядка) appWithTranslation, который предоставляется экземпляром NextI18Next, который мы создали ранее. Кроме того, мы должны добавить строки 8–12, чтобы сделать функцию getInitialProps нашего компонента асинхронной.

И, наконец, мы должны зарегистрировать наши localeSubpaths внутри next.config.js, чтобы наше приложение Next.js знало, как обрабатывать такие запросы, как https://example.com/es/about (даже если страница pages/es/about.js как файл не существует):

Файлы перевода

Прежде чем мы сможем создать наше приложение, нам нужно создать файлы перевода в нужном месте. Эти файлы содержат строки, которые мы показываем конечному пользователю в интерфейсе:

Внутри каталога public/static/locales мы создаем каталоги для каждого из наших языков: en, es, nl и no.
Внутри каждого из этих каталогов вы можете увидеть два файла:

  • about.json
  • common.json

Эти файлы или, по крайней мере, их имена (без расширения) представляют пространства имен. Вам не обязательно использовать это, но это позволяет нам разделять переводы на более мелкие части. Возможно, вам нужно пространство имен product-descriptions, в котором вы переводите все названия своих продуктов, и общее пространство имен, в котором вы храните все остальные переводы.

Как видите, мы создаем эти файлы пространств имен для всех наших языков.

В качестве примера рассмотрим содержимое public/static/locales/es/about.json:

И public/static/locales/es/common.json:

Я полагаю, вы можете представить, как выглядят файлы для других языков.

Не забывайте об этих файлах по мере продвижения!

Отображение переведенных строк

Все настроено, и пора использовать (переведенные) строки в наших компонентах:

Это наш компонент О странице. Мы оборачиваем его в withTranslation HOC, который предоставляет опору «t» (среди других свойств).

Мы также определяем getInitialsProps для загрузки пространств имен (помните файлы about.json и common.json?), Которые нас интересуют. Это особенно важно, если у вас есть более крупное приложение с большим количеством пространств имен: by default, загружаются все пространства имен, и, возможно, вы хотите предотвратить это из соображений производительности.

Обратите внимание, как мы повторяем массив имен пространств имен в строке 17. Это необходимо.

В строках 7 и 8 вы можете увидеть, как мы используем функцию «t». Он ожидает один аргумент, который является именем переведенной строки:

  • Строка 7: t(“common:about”)
  • Строка 8: t(“aboutMessage”)

Аргумент в строке 7 содержит префикс пространства имен (common:). Это можно использовать, если возникают конфликты имен для одинаковых имен, определенных в разных пространствах имен.

Функция «t» вернет правильную строку в зависимости от текущего установленного языкового стандарта (языка). Но как мы можем прочитать и изменить текущий язык?

Текущий язык (локаль)

По умолчанию загружается локаль для нашего defaultLanguage: «en», что соответствует английскому языку. Это мы настроили ранее в src/i18n.js как язык по умолчанию.

Внутри компонента мы можем получить текущий язык, прочитав next-i18next context с помощью ловушки useContext из React:

Мы можем установить (изменить) текущий язык, используя функцию changeLanguage из нашего экземпляра NextI18Next, который мы создали внутри файла src/i18n.js:

Эта функция за кулисами творит много волшебства. Без обновления страницы все переведенные строки переводятся в их новые значения с помощью функции «t», а также обновляется URL-путь (обратите внимание на адресную строку на этом анимированном гифке):

Отображение локализованных дат

Наконец, небольшой совет о том, как локализовать даты, то, что также видно на анимации выше. Мы используем библиотеку Luxon для анализа и форматирования дат.

Мы можем просто передать текущий язык (локаль) нашему экземпляру DateTime:

Как вы, возможно, читали в моих статьях о Luxon (часть 1, часть 2), использование этой библиотеки прямолинейно и справедливо. Легко понять.

На этом пока все!

Исходный код этой статьи можно найти на GitLab.

Спасибо за ваше время.

Жерар ван дер Пут