Внедрение i18n в Next.js: руководство по локализации, не основанной на маршрутах

Внедрение i18n в Next.js: руководство по локализации, не основанной на маршрутах

23 февраля 2023 г.

Мотивация

Недавно мы перенесли наш подпроект с react-localization на i18next. Во время этой миграции основной целью было сохранить предыдущее поведение установки и изменения языка в нашем приложении.

Хранение языка в пути маршрута является широко используемой практикой для платформы Nextjs. Но для нашего проекта это было неподходящее решение.

Наше основное приложение позволяет предприятиям генерировать QR-коды для своих клиентов со ссылкой на дополнительное приложение, где конечный пользователь может оставить отзыв о качестве обслуживания и удовлетворенности им.

Все QR-коды уже были напечатаны, а новые обойдутся бизнесу в целое состояние. Предыдущая версия подприложения была построена на базе CRA, и всего полгода назад она была мигрирована на Nextjs.

Итак, мы искали библиотеку или библиотеки, которые могли бы предоставить нам интернационализацию, не основанную на маршрутах, и API, подобный react-i88next.

Мы нашли ni18n. Это библиотека, специально разработанная для использования с Nextjs. ni18n предоставляет простой и гибкий способ добавления функций i18n в проекты Nextjs, включая поддержку рендеринга на стороне сервера и другие расширенные функции.

Базовая настройка

Давайте установим все необходимые зависимости, чтобы начать работу над нашим проектом.

npm install i18next react-i18next ni18n

Следующим шагом является расширение существующего next.config.js конфигурацией i18n по умолчанию.

По сути, нам нужно всего несколько полей для быстрого старта. locales требуется для отображения всех локалей, которые мы хотим поддерживать в приложении, а defaultLocale будет использоваться при посещении пути с префиксом, не относящимся к локали (для нас это просто язык по умолчанию).

// next.config.js
module.exports = {
    ...yourNextConfig,
  i18n: {
    defaultLocale: 'GB',
    locales: ['GB', 'UA', 'PT'],
  },
};

Затем нам необходимо создать новый файл в корне или utils/plugins/etc. каталог с именем ni18n.config.js . supportedLngs — имена, которые показывают нам поддерживаемые языки, и ns — пространства имен, которые мы можем использовать в некоторых случаях.

// ni18n.config.js
export const ni18nConfig = {
  supportedLngs: ['GB', 'UA', 'PT'],
  ns: ['namespace-name'],
};

Осталось еще несколько вещей. Нашему приложению требуется I18nextProvider, поэтому давайте обернем App высокоуровневым компонентом, импортированным из i18n.

Он инициализирует экземпляр i18next и предоставит его в качестве контекста для всех дочерних элементов.

// pages/_app.jsx
import { appWithI18Next } from 'ni18n';
import { ni18nConfig } from '../ni18n.config';

const App = ({ Component, pageProps }) => <Component {...pageProps} />;

export default appWithI18Next(App, ni18nConfig);

И последний этап подготовки перед тем, как мы начали использовать перевод в наших компонентах, это заполнение файлов перевода. Главное - сохранить следующую структуру файлов.

./public
└── locales
    ├── GB
       ├── namespace-name.json  // { "key1": "Test" }
    
    ├── UA
       ├── namespace-name.json  // { "key1": "Тест" }
    
    ├── PT
        ├── namespace-name.json  // { "key1": "Teste" }

Наконец, мы закончили настройку и готовы начать интеграцию функции i18n в компоненты. Давайте посмотрим на пример в ComponentName.jsx.

Мы извлекаем функцию t из хука useTranslation, который возвращает переведенную строку для выбранного языка. Выглядит просто, не так ли?

// ComponentName.jsx
import { useTranslation } from 'react-i18next';

export const MyComponent = () => {
  const { t } = useTranslation();
  return (
        <div>{t('key1')}</div>
    );
};

Если вы храните пользовательский язык в БД, не забудьте создать контекст с помощью React.Context или любого другого решения для переноса страниц и установить язык в useEffect. Ниже я покажу вам простой фрагмент того, как это можно реализовать.

// ContextName.jsx
const I18nProvider = ({ children, data }) => {
    const { i18n } = useTranslation();

    const { language = 'GB' } = data;

    useEffect(() => {
        i18n.changeLanguage(language);
    }, [language]);

    return (
        <I18nContext.Provider>
            {children}
        </I18nContext.Provider>
    );
};

Вот и все. Я надеюсь, что это помогло вам сэкономить немного времени, как всегда. В будущем мы собираемся перенести существующий подход i18n на маршрутный. Причина довольно проста — унификация всех наших приложений. Обязательно опишу в одной из следующих статей.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE