Мультиязычность ngx-translate в Angular 9 c монорепозиторием Nx.
В данной статье поговорим о подходах мультиязычности в Angular 9 с использованием монорепозитория Nx. Рассмотрим механизм локализации в Angular, приведём решение для Angular Universal (SSR).
В предыдущей статье — Internationalization в Angular с помощью ngx-translate, в которой уже описаны основные подходы и принципы. В данной статье мы актуализируем знания и немного изменим SSR реализацию, изменения которой вызваны изменениями серверной сборки.
Подробнее про новые изменения и настройку SSR приложений в Angular, можно прочитать в статье — Angular 9, Universal и Nx. Новые правила сборки SSR приложения.
В Angular есть два подхода для реализации мультиязычности.
Первый подход построен на стандартной реализации локализации — angular/i18n. В основе подхода находится международный стандарт CLDR (Common Locale Data Repository|Общий Репозиторий Языковых Данных).
Второй подход это использование ngx-translate, принцип работы которого заключается в сопоставлении ключей и переводов к ним, для заданных локалей.
Ранее, автор был сторонником второго подхода, так как видел существенные недостатки первого подхода — невозможность смены языка без перезагрузки. Но спустя время, поддерживая и развивая мультиязычный проект, автор столкнулся с минусами и второго подхода — сложность поддержки локализации текста, содержащего HTML. Также явная потребность в смене языка без перезагрузки отсутствует.
Настройка локализации
В данной статье будет рассмотрен второй подход.
Установка зависимостей
Для установки ngx-translate достаточно установить два пакета:
yarn add @ngx-translate/core @ngx-translate/http-loader
- ngx-translate/core — реализация мультиязычности и соответствующих сервисов и пайпов
- ngx-translate/http-loader — загрузчик локали по http, который используется для браузерной версии приложения
Если у вас не настроен Universal, но вы хотите получить SSR приложение, тогда, прежде чем продолжить, ознакомьтесь с документацией и со статьей.
Подключение локализации
Сначала подключим локализацию для браузерной версии.
В файле app.browser.module.ts (или app.module.ts, если вы не меняли названия или не приводили проект к ssr) добавим следующий конфиг:
Как видно, в imports был добавлен TranslateModule:
- TRANSLATION_PREFIX — префикс, который будет использоваться лоадером, чтобы найти файл при загрузке файла, который по умолчанию равен ‘assets/i18n’
- TRANSLATION_SUFFIX — суффикс, который определяет расширения файла локали, который по умолчанию равен ‘.json’.
Функция translateHttpFactory, которая в данном контексте является фабрикой и создаёт новый загрузчик локализации для TranslateModule.
Данных настроек достаточно для работы браузерной версии. Теперь перейдём к настройке серверной части.
Для этого создадим серверный загрузчик, который будет брать локаль не по http, а с папки, где размещается браузерная версия приложения:
Серверный загрузчик — ServerTranslateLoader, просто с помощью пакетов NodeJS, открывает файл и возвращает локаль.
Фабрика по созданию загрузчика — serverTranslateFactory, как и в предыдущем примере, принимает два аргумента prefix и suffix, которые являются путём расположения файлов и расширением соответственно. Параметр appDist, является необходимым параметром только в монорепозитории Nx, чтобы выбрать локаль из нужного проекта. Поэтому, если вы не используете Nx, просто не передавайте в фабрику данный параметр.
Подключим загрузчик в app.server.module.ts:
TranslateModule сконфигурирован и его можно использовать.
Отметим, разработчик должен сам реализовать сохранение выбранной локали и её восстановление при перезагрузке приложения. Или же реализовать модуль translation, о котором будет рассказано ниже.
Translation Module
Как можно заметить, ngx-translate хранит информацию о локали внутри сервиса.
Для того чтобы настройки локали сохранялись нужен сервис, который будет сохранять настройки локали в веб хранилище или куки. А также сервис, который при первой загрузке приложения будет восстанавливать настройки из хранилища.
Так как автор сторонник использования Redux, данная функциональность будет вынесена в TranslationState. Но как говорилось ранее, потребность локализации и её смене настолько мала, что вместо того, чтобы создавать множество файлов для реализации и поддержки state, достаточно вызвать один метод класса сервиса — init.
Объявление интерфейсов
Сначала добавим интерфейс для настроек локали и сервиса, который будет сохранять настройки.
TranslationStorage:
TranslationService:
Вынесем токены в один общий файл:
Реализация сервисов
Добавим реализацию для TranslationStorage:
Добавим реализацию для TranslationService:
Добавим конфигурацию для TranslationModule и сам модуль:
Как видно из реализации, используется APP_INITIALIZER, для определения инициализации приложения и запуск сервиса установки языка.
Отметим, что translationLoader возвращает промис, а это значит, что приложение не отрисуется пока не выполняться все APP_INITIALIZER промисы.
Добавим TranslationModule в AppModule и запустим проект:
Все отлично работает.
TranslationState
Если вам по какой-то необходимости необходимо вынести все события в Redux, то приведём реализацию с TranslateState:
Заметим, что state разработан с предыдущим style guide от Nx. В последней версии style guide Nx, удалось сократить дублирование кода. Подробнее можно посмотреть в схемах Nx.
Добавим наш state в TranslationModule:
Запустим и убедимся, что это тоже работает как и предыдущий вариант:
Резюме
Обобщая выше сказанное, в данной статье:
- Поговорили о способах реализации мультиязычности в Angular.
- Выбрали в качестве мультиязычности подход перевода методом ключ — значение, предоставляемое ngx-translate.
- Произвели установку и настройку ngx-translate для браузерной и серверной версий.
- Привели решение для сохранения и восстановления локали, реализовав TranslationModule в двух вариантах с и без использования ngrx.
Исходники
Все исходники находятся на github, в репозитории:
Для того, чтобы посмотреть состояние проекта на момент написания статьи, нужно выбрать соответствующий тег — translation-second.
git checkout translation-second
Код можно посмотреть в разделе https://github.com/Fafnur/medium-stories/tree/master/apps/frontend/translation.
Спасибо за внимание!
Подписывайтесь на канал, чтобы не пропустить новые статьи про Angular и новости из мира фронтенд разработки.
Предыдущие статьи:
- GraphQL API для Angular с помощью NX и Nest.
- Интеграция GraphQL API в Angular приложение
- Динамические формы в Angular или автоматизируем создание Angular форм
- Создание переменных в шаблонах Angular. Превращение реактивных свойств в простые объекты.
- Angular 9, Universal и Nx. Новые правила сборки SSR приложения.
- Кроссплатформенные web storage в Angular 9. Реализация LocalStorage, SessionStorage и Cookies в Angular Universal.