Локализация

  • Устройство
  • 3 мин
  • кода: 2

Библиотека не заводит свой i18n-стек: локаль, словари и хранение выбора остаются за приложением. Три языка в поставке.

Ревизия 2026-10-16

На этой странице

Пакет не навязывает приложению отдельный i18n-стек и не создаёт свой инстанс. Локаль, запасная локаль, хранение выбранного языка и объединение словарей — работа приложения; библиотека лишь спрашивает у него перевод по ключу.

Как это работает

  1. Компонент запрашивает строку по ключу вида gr.pagination.prev.
  2. Есть перевод — используется он.
  3. Слой не подключён или вернул сам ключ — компонент берёт встроенный запасной текст.

Третий шаг важнее, чем кажется: отсутствие перевода не ломает интерфейс. Пакет можно подключать поэтапно, а часть служебных строк вынести в словари позже — компоненты продолжат работать по-английски.

Что в поставке

Библиотека везёт словари трёх языков: английский, испанский и русский. Все три полные — состав ключей сверяется гейтом пакета, а не глазами.

Портал, который вы читаете, говорит на двух языках, а библиотека — на трёх. Расхождение не ошибка: испанский словарь ядра полон и работоспособен, документации на испанском просто ещё нет.

Подключение

Рекомендуемый слой — @feugene/fint-i18n: он объявлен необязательной peer-зависимостью и хорошо ложится на подход, где приложение владеет всем. Если в проекте уже есть зрелый i18n, пакет встраивается и в него.

ts
import { createFintI18n } from '@feugene/fint-i18n/core'
import { installI18n } from '@feugene/fint-i18n/vue'
import { GRANULARITY_I18N_BLOCK, en, ru } from '@feugene/granularity/i18n'

const i18n = createFintI18n({
  locale: 'ru',
  fallbackLocale: 'en',
  loaders: [en, ru],
})

i18n.registerBlocks([GRANULARITY_I18N_BLOCK])
await i18n.loadUsedBlocks('ru')

// Без этого пакет не найдёт инстанс через provide/inject
// и останется на встроенных текстах.
installI18n(app, i18n)

Подпуть @feugene/granularity/i18n отдаёт блок gr, ленивые загрузчики en, es, ru и ключ адаптера с типами. Загрузчики по локалям — именно то, что нужно в бою: бандлер вытряхивает неиспользуемые языки. Агрегат всех локалей сразу лежит отдельно, в @feugene/granularity/i18n/all, и предназначен для демо, e2e и инструментов.

Пакеты-спутники

У каждого спутника свой блок строк — GR_CHRONO_I18N_BLOCK (grChrono), GR_MEDIA_I18N_BLOCK (grMedia) и так далее, — и подключаются они в тот же инстанс, рядом с основным:

ts
import { GRANULARITY_I18N_BLOCK, en as coreEn, ru as coreRu } from '@feugene/granularity/i18n'
import { GR_CHRONO_I18N_BLOCK, en, ru } from '@feugene/granularity-chrono/i18n'

const i18n = createFintI18n({ locale: 'ru', fallbackLocale: 'en', loaders: [coreEn, coreRu, en, ru] })
i18n.registerBlocks([GRANULARITY_I18N_BLOCK, GR_CHRONO_I18N_BLOCK])

Один i18n-слой на всё приложение — и продуктовые экраны, и дизайн-система.

Что не приходит из словарей

Календарь, время и относительные даты берут из Intl всё, что зависит от локали: названия месяцев и дней недели, первый день недели, порядок разбора даты, выбор 12- или 24-часового формата. Словарь несёт только строки интерфейса — подписи, aria-label, заголовки панелей.

Практическое следствие: компоненты дат говорят на всех языках, которые знает движок, а не на трёх перечисленных.

Переопределение строк

Менять подписи, кнопки, aria-label и служебные сообщения нужно в словаре приложения, а не форком пакета. Так терминология остаётся под единым контролем, а обновление библиотеки не превращается в разбор конфликтов.

Смена языка и провайдер

GrConfigProvider принимает проп locale, но это просьба к адаптеру переключиться, а не источник истины: провайдер локаль не хранит и не подменяет. Адаптер своего контракта он просит через syncLocale, а у инстанса fint-i18n, где такого метода нет, зовёт setLocale() — тот же вызов, которым язык переключают напрямую: i18n.setLocale('en'). Адаптер из пропа i18n отдаётся вниз через фасад, а не значением, — поэтому адаптер, созданный асинхронно, доедет до компонентов, когда появится, а подмена адаптера перерисует строки. Без пропа фасад делегирует адаптеру выше по дереву, в том числе установленному через installI18n. См. конфигурацию.