Сайт визитка на Angular. Настройка локализации.
В данной статье рассмотрим интеграцию локализации в приложении.
При создании приложения, в проект уже были добавлены модули локализации.
Для установки локализации достаточно установить пакет
nx add @angular/localize
Так как в приложении используется русский язык, то необходимо сконфигурировать все сервисы, чтобы они использовали русскую локализацию.
Сначала сконфигурируем локализацию в настройках сборки, где в файл проекта добавим локализацию apps/store/project.json
:
{
"projectType": "application",
"root": "apps/store",
"sourceRoot": "apps/store/src",
"prefix": "banshop",
...
"i18n": {
"sourceLocale": "en-US",
"locales": {
"ru-RU": {
"translation": "libs/russian/localization/src/lib/messages.xlf",
"baseHref": ""
}
}
},
...
}
Как видно из настроек, файл локализации размещается в libs/russian/localization/src/lib/messages.xlf
.
Для браузерной сборки укажем локализацию:
"build": {
...
"options": {
...
"localize": ["ru-RU"],
},
...
}
Для серверной версии все не так однозначно.
Из-за того, что dev-server не может корректно подключить локаль, то для сервреной сборки указывается localize: false
, а для production
уже ставится верная локаль:
"server": {
"executor": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/store/server",
"main": "apps/store/server.ts",
"tsConfig": "apps/store/tsconfig.server.json",
"inlineStyleLanguage": "scss",
"localize": false
},
"configurations": {
"production": {
"localize": ["ru-RU"],
"outputHashing": "media",
"fileReplacements": [
{
"replace": "apps/store/src/environments/environment.ts",
"with": "apps/store/src/environments/environment.prod.ts"
}
],
"bundleDependencies": true
},
"development": {
"localize": ["ru-RU"],
"optimization": false,
"sourceMap": true,
"extractLicenses": false
},
"ru": {
"optimization": false,
"sourceMap": true,
"extractLicenses": false
}
},
"defaultConfiguration": "production"
},
И тогда для запуска serve-ssr
меняем конфигурацию на ru
:
"serve-ssr": {
"executor": "@nguniversal/builders:ssr-dev-server",
"configurations": {
"development": {
"browserTarget": "store:build:development",
"serverTarget": "store:server:ru"
},
"production": {
"browserTarget": "store:build:production",
"serverTarget": "store:server:production"
}
},
"defaultConfiguration": "development"
},
Localication Module
Для это создадим отельный модуль, который будет подключаться в AppCoreModule
.
Добавим новую библиотеку:
nx g lib russian/localization
В приложении используется маски. И так как шаблоны в разных странах специфичны, добавим сервис, который будет предоставлять доступ к русским форматам масок телефонов и пр.
Формат даты также отличается от страны к стране.
Создадим адаптер дат, для корректной работы с Angular Material
:
Определим локаль в модуле и подключим выше созданные сервисы:
LOCALE_ID
— токен текущей локализации в приложении. Его используют все пайпы, которые зависят от локали;DEFAULT_CURRENCY_CODE
— токен, который содержит в себе тип валюты;MAT_DATE_LOCALE
— токен с текущей локализации в Angular MaterialDateAdapter
— адаптер даты;FormMaskService
— сервис для работы с масками;MAT_RADIO_DEFAULT_OPTIONS
— токен, который устанавливает цвет по умолчанию для радио кнопок в приложении;MAT_CHECKBOX_DEFAULT_OPTIONS
— токен, который устанавливает цвет по умолчанию для чекбоксов в приложении.
Для того, чтобы Angular загрузил локализированные данные, в приложение импортируется и регистрируется русская дата:
import { registerLocaleData } from '@angular/common';
import localeRu from '@angular/common/locales/ru';
registerLocaleData(localeRu);
Локализация компонентов
В предыдущих статьях было видно, что все компоненты по умолчанию используют английский язык. Для задачи русского языка, каждый элемент шаблона имел специализированную директиву — i18n
.
Пример ее использования на странице ошибок:
<banshop-error-title i18n="Error not found|Title">
Page not found
</banshop-error-title>
Формат задания следующий: сначала идет тип перевода, потом описание, которое должно помочь переводчику.
Если запустить команду локазации, то Angular сгенерирует новый файл локализкации:
nx extract-i18n store --out-file=libs/russian/localization/src/lib/source.xlf
Из команды видно, что файл локализации сохраниться в libs/russian/localization/src/lib/source.xlf
.
Для примера выше будет создан файл source.xlf
:
trans-unit
— объект перевода, гдеid
уникальный идентификатор для строки перевода;source
— исходный перевод;context-group
— содержит информацию о размещении переводаnote
— замечания к переводу.
Для того чтобы добавить перевод, необходимо после source
создать новый тег:
<target state="translated">Страница не найдена</target>
Если добавить данный тег, то тогда строка в приложении «Page not found» перейдет в «Страница не найдена».
Итоговый файл:
<trans-unit id="c9be140e4b3e7fe071d29de65b243fb4e2a6bbba" datatype="html">
<source>Page not found</source>
<target state="translated">Страница не найдена</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/errors/not-found/page/src/lib/not-found-page.component.html</context>
<context context-type="linenumber">3</context>
</context-group>
<note priority="1" from="description">Title</note>
<note priority="1" from="meaning">Error not found</note>
</trans-unit>
Для локализации внутри компонентов, используется глобальная переменная $localize
.
Пример использования:
{
title: $localize`:Errors server|:Internal server error | Banshop`,
}
В данном случае, если в шаблонах локализации является вертикальная черта “|”, то внутри компонентов это “:”.
Для того, что linter
не ругался, необходимо в файл библиотеки или приложения, в файл tsconfig.lib.json
добавлять тип глобальной переменной:
Множественное число с локализацией является простой задачей.
Разберем компонент, в котором выводится количество товаров в корзине.
Шаблон, отвечающий за вывод количества товаров будет следующим:
<div i18n="Cart info|Cart count">
{cartProducts | cartTotalCount, plural, =0 {no products} =1 {1 product} other { {{ cartProducts | cartTotalCount }} products} } in the cart.
</div>
Как видно из примера, для английского мы имеем пример, где корректными формами будут 1 product и 2 products (3 products, 4 products, …).
В русском же мы имеем 3 варианта: 1 товар, 2 товара, 3 товара, 4 товара и 5 товаров, и т.д.
Правила для русского будут определяться именно в файле локализации, а не в шаблоне.
Исходная фраза:
<source> <x id="ICU" equiv-text="{cartProducts | cartTotalCount, plural, =0 {no products} =1 {1 product} other {
{{ cartProducts | cartTotalCount }} products} }"/> in the cart. </source>
Будет заменена:
<target state="translated">
В корзине
<x id="ICU" equiv-text="{cartProducts | cartTotalCount, plural, =0 {no products} =1 {1 product} other { {{ cartProducts | cartTotalCount }} products} }"
/></target>
Сначала переводится все то, что не отвечает за количество, в частности фраза “В корзине”.
Затем отдельно переводится случай с множественными числами:
<source>{VAR_PLURAL, plural, =0 {no products} =1 {1 product} other {<x id="INTERPOLATION"/> products}}</source>
Трансформируется в:
<target state="translated">{VAR_PLURAL, plural, =0 {пусто} =1 {1 товар} =2 {2 товара} =3 {3 товара} =4 {4 товара} other {<x id="INTERPOLATION"/> товаров}}</target>
Локализация страниц
Иногда есть потребность в переводе больших частей текста, например, договоров, оферты, индивидуальных условий и других документов. Что делать в этом случае?
Самым худшим решением будет создать на каждый абзац i18n
, и перевести с помощью пакета локализации.
Лучшим решением будет создания статичного, не переводимого текста. Просто создайте новый модуль, который жестко зависит от локали и используется только в ее рамках.
Разберем страницу условий продажи в приложении.
Создадим новую библиотеку для условий продажи:
nx g lib russian/terms/page
Как видно из команды, страница с условиями располагается в папке russian
, что говорит о том, что данная страница должна использоваться только в России и нигде более.
Добавим компонент и соответствующий текст:
nx g с terms-page --project=russian-terms-page
Как видно из примера, компонент не использует инструменты локализации, а просто выводит статичный текст.
Ссылки
Предыдущая статья — Страницы ошибок.
Следующая статья — Настройка SEO.
Все исходники находятся на github, в репозитории:
Для того, чтобы посмотреть состояние проекта на момент написания статьи, нужно выбрать соответствующий тег — article.
Подписывайтесь на блог, чтобы не пропустить новые статьи про Angular, и веб-разработку. Medium | Telegram| VK |Tw| Ln