# Локализация

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

- Page: https://granularity.tech/ru/docs/localization
- Last reviewed: 2026-10-16

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

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

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

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

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

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

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

## Подключение

Рекомендуемый слой — `@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`. См. [конфигурацию](/ru/docs/configuration).
