# @coopenomics/i18n

> Словари интерфейса, каталог кодов ошибок и форматирование: один формат сообщений для desktop, controller и уведомлений

Latest version **2026.9.24-3** (published 2026-09-24) · MIT license · 0 weekly downloads

## Install

```sh
npm install @coopenomics/i18n
pnpm add @coopenomics/i18n
yarn add @coopenomics/i18n
bun add @coopenomics/i18n
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 2026.9.24-3 |
| Published | 2026-09-24 |
| First published | 2026-09-24 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 102.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Alex Ant <dacom.dark.sun@gmail.com> |
| Maintainers | sysarch |

## Links

- npm: https://www.npmjs.com/package/@coopenomics/i18n
- npm.io page: https://npm.io/package/@coopenomics/i18n

## Dependencies (1)

- [@intlify/core-base](https://npm.io/package/@intlify/core-base.md) ^11.4.12

## Recent versions

- 2026.9.24-3 (latest) — 2026-09-24
- 2026.9.24-2 — 2026-09-24

## README

# @coopenomics/i18n

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

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

| Модуль | Что делает |
|---|---|
| `locales` | список языков (`SUPPORTED_LOCALES`), язык по умолчанию, выбор языка из `Accept-Language` |
| `plural` | правила множественного числа для vue-i18n: `{n} день \| {n} дня \| {n} дней` |
| `messages` | слияние словарей с запретом повторных ключей, поиск по ключу |
| `translator` | переводчик на ядре vue-i18n (`@intlify/core-base`) для кода без Vue |
| `pseudo` | псевдолокаль `ru-XA` для проверки глазами |
| `format` | числа и суммы по правилам языка (`Intl`) |
| `server` | язык запроса (AsyncLocalStorage), реестр словарей процесса, `t()` |
| `messages/ru/*.json` | общие словари: `common`, `validation`, `errors` |

desktop подключает словари и правила в vue-i18n, controller и уведомления —
через `@coopenomics/i18n/server`. Формат сообщений везде один.

## Формат сообщений

Синтаксис vue-i18n:

| Что | Пример | Вызов |
|---|---|---|
| именованный параметр | `Привет, {name}!` | `t('k', { name })` |
| позиционный параметр | `{0} из {1}` | `t('k', [a, b])` |
| формы по числу | `{n} день \| {n} дня \| {n} дней` | `t('k', n)` |
| форма для нуля | `нет дней \| {n} день \| {n} дня \| {n} дней` | `t('k', n)` |
| ссылка на сообщение | `Итог: @:wallet.balance` | — |
| служебный символ как текст | `почта{'@'}coop.ru` | — |

Символы `{ } @ |` в обычном тексте экранируются литералом: `{'@'}`, `{'{'}`,
`{'|'}`. Гейт `pnpm check:i18n` компилирует каждое сообщение и падает на
ошибке синтаксиса.

## Ключи

Английские, смысловые, от области к элементу, в camelCase:

```
<область>.<сущность или экран>.<элемент>
wallet.deposit.submit
wallet.deposit.amountLabel
capital.issue.status.draft
common.action.save
```

- **Область** — домен FSD-среза (`wallet`, `document`, `registrator`)
  или имя расширения (`capital`, `chairman`). Все ключи расширения лежат
  под его именем.
- **Сущность или экран** — компонент, диалог, форма, сообщение
  (`deposit`, `exitDialog`, `notify`).
- **Элемент** — роль текста: `title`, `subtitle`, `label`, `hint`,
  `placeholder`, `submit`, `empty`, `success`, `confirm`, либо смысловое
  имя (`amountLabel`, `minAmountHint`).
- Статусы и перечисления — `<область>.<сущность>.status.<значение>`,
  значение как в коде.
- Общие для всего приложения фразы — в `common.*` этого пакета. Два экрана
  делят ключ, только если фраза совпадает и по смыслу, а не случайно.
- Имена параметров — смысловые: `{amount}`, `{date}`, `{username}`.

## Ошибки

Ошибка для клиента несёт код, а текст подставляет сервер на языке запроса.
Код — `SCREAMING_SNAKE` с префиксом области (`WALLET_INSUFFICIENT_FUNDS`,
`CAPITAL_ISSUE_NOT_FOUND`), сообщение — по ключу `errors.<КОД>`. Общие коды
(`COMMON_*`, `CHAIN_ASSERT`) — в этом пакете, коды расширения — в словаре
расширения.

## Где лежат словари

| Кто | Где |
|---|---|
| общие | `components/i18n/src/messages/<язык>/*.json` |
| ядро desktop | `components/desktop/src/shared/i18n/locales/<язык>/<область>.json` |
| расширение desktop | `components/desktop/extensions/<имя>/i18n/<язык>.json` |
| ядро controller | `components/controller/src/i18n/locales/<язык>/<область>.json` |
| расширение controller | `components/controller/src/extensions/<имя>/i18n/<язык>.json` |

Документация остаётся по-русски: описания GraphQL-схемы, комментарии и логи
в словари не выносятся.

## Как писать код

| Где | Как |
|---|---|
| шаблон desktop | `{{ $t('wallet.deposit.title') }}`, `:label="$t('common.action.save')"` |
| скрипт desktop | `import { t } from 'src/shared/i18n'` — ядро; `import { t } from '<расширение>/i18n'` — расширение |
| отказ бэкенда | `throw DomainError.notFound('WALLET_NOT_FOUND', { username })` — из `@coopenomics/extension-kit` |
| сообщение class-validator | `@IsNotEmpty({ message: validationMessage('account.form.emailRequired') })` — переводится в момент проверки |
| надпись бэкенда | `import { t } from '~/i18n'` (ядро) или `'../i18n'` (расширение) |
| клиентская библиотека (auth, sdk) | `import { lt } from '@coopenomics/i18n'`; приложение подставляет свой переводчик через `setLibraryTranslator` |
| уведомление | тексты — `components/notifications/src/i18n/ru.json` (Liquid), в сценарии — `nt('<сценарий>.<канал>.<поле>')` |
| отказ по коду на клиенте | `hasErrorCode(error, 'MEMBERSHIP_EXIT_PAYMENT_METHOD_REQUIRED')` из `src/shared/api/errors` — не по тексту |

Строка, которая не является текстом интерфейса (данные, маски, имена XML-элементов
официальных форм, сверка с текстом отказа контракта), помечается комментарием
`// i18n-ignore: причина` на той же или предыдущей строке; файл-данные целиком —
`// i18n-ignore-file: причина` в начале. Строки шаблонов, которые нельзя пометить
комментарием, перечислены в `scripts/lib/i18n-ignore.json`.

SSR-middleware (`src-ssr`) и сервис-воркер собираются без Vite и переводчик
приложения не импортируют — гейт это проверяет.

## Гейт и инструмент переноса

`pnpm check:i18n` (входит в `pnpm check`) — хардкод кириллицы храповиком
(`scripts/lib/i18n-hardcode-baseline.json`, сейчас 0), исправность словарей,
подключение словарей расширений, типы ключей (`keys.generated.ts`), глоссарий
(`glossary.json`), шаблоны уведомлений.

`node scripts/i18n-extract.mjs scan <пути> --out work.json` → разметка ключей
(`names.json`) → `node scripts/i18n-extract.mjs apply work.json names.json` —
механический перенос строк: замена в шаблонах и скриптах, `DomainError` вместо
исключений бэкенда, словари, импорты, подключение словаря расширения.
После — `node scripts/check-i18n.mjs types --write` и `hardcode --update`.

---
_Source: https://npm.io/package/@coopenomics/i18n · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
