Библиотека FormatJS опирается на стандарт Unicode CLDR (Common Locale Data Repository) — крупнейшее централизованное хранилище локализационных данных, поддерживаемое консорциумом Unicode. Именно CLDR определяет, как приложения должны отображать даты, числа, валюты, единицы измерения, имена языков, регионов и правила множественного числа для разных локалей.
FormatJS не изобретает собственные механизмы локализации. Вместо
этого библиотека использует стандарты платформы ECMAScript
Internationalization API (Intl), а сами данные и правила
берутся из CLDR.
CLDR представляет собой набор структурированных данных, описывающих особенности локалей:
Пример различий между локалями:
| Локаль | Формат даты | Разделитель дробной части |
|---|---|---|
en-US |
12/31/2025 |
. |
de-DE |
31.12.2025 |
, |
fr-FR |
31/12/2025 |
, |
ja-JP |
2025/12/31 |
. |
Все эти различия определяются именно CLDR.
FormatJS работает поверх Intl.* API:
new Intl.DateTimeFormat('fr-FR')
new Intl.NumberFormat('de-DE')
new Intl.PluralRules('ru')
Движок JavaScript получает данные локализации из реализации ICU (International Components for Unicode), а ICU использует CLDR как источник данных.
Схема зависимости:
CLDR
↓
ICU
↓
Intl API
↓
FormatJS
↓
Приложение
Таким образом:
Intl предоставляет API;Локаль состоит из нескольких компонентов:
language-Script-Region-Variant
Примеры:
| Локаль | Значение |
|---|---|
en |
английский |
en-US |
английский (США) |
en-GB |
английский (Великобритания) |
zh-Hans |
китайский упрощённый |
zh-Hant |
китайский традиционный |
sr-Cyrl |
сербский кириллица |
sr-Latn |
сербский латиница |
FormatJS полностью поддерживает BCP 47 locale identifiers, основанные на стандартах Unicode.
Наиболее часто локаль задаётся через IntlProvider.
import { IntlProvider } from 'react-intl'
<IntlProvider locale="ru">
<App />
</IntlProvider>
Внутри:
locale="ru" активирует русские правила CLDR;CLDR определяет:
new Intl.NumberFormat('en-US').format(1234567.89)
Результат:
1,234,567.89
Для немецкой локали:
new Intl.NumberFormat('de-DE').format(1234567.89)
Результат:
1.234.567,89
Разница полностью определяется CLDR.
CLDR содержит:
intl.formatNumber(1000, {
style: 'currency',
currency: 'USD'
})
Для en-US:
$1,000.00
Для fr-FR:
1 000,00 $US
Для ja-JP:
US$1,000.00
CLDR содержит сокращённые формы записи больших чисел.
intl.formatNumber(1200000, {
notation: 'compact'
})
Для английского:
1.2M
Для русского:
1,2 млн
Для японского:
120万
CLDR хранит:
intl.formatDate(new Date(), {
dateStyle: 'full'
})
Для en-US:
Thursday, May 28, 2026
Для ru-RU:
четверг, 28 мая 2026 г.
Для ar-EG:
الخميس، ٢٨ مايو ٢٠٢٦
CLDR поддерживает множество календарных систем:
new Intl.DateTimeFormat('ja-JP-u-ca-japanese')
Результат:
R8/05/28
Используется японская эра вместо григорианского года.
Plural Rules — одна из важнейших частей CLDR.
Разные языки имеют разные категории:
| Язык | Категории |
|---|---|
| English | one, other |
| Russian | one, few, many, other |
| Arabic | zero, one, two, few, many, other |
Русский язык имеет сложную систему:
| Число | Категория |
|---|---|
| 1 | one |
| 2 | few |
| 5 | many |
| 21 | one |
| 32 | few |
| 100 | many |
FormatJS использует эти правила автоматически.
intl.formatMessage(
{
defaultMessage:
'{count, plural, one {# файл} few {# файла} many {# файлов} other {# файла}}'
},
{ count: 5 }
)
Результат:
5 файлов
FormatJS использует ICU MessageFormat.
Pluralization напрямую связана с CLDR:
{
count,
plural,
one {# item}
other {# items}
}
Для русского:
{
count,
plural,
one {# комментарий}
few {# комментария}
many {# комментариев}
other {# комментария}
}
CLDR определяет следующие категории:
| Категория | Назначение |
|---|---|
| zero | ноль |
| one | единственное |
| two | двойственное |
| few | несколько |
| many | много |
| other | остальные |
Не все языки используют все категории.
CLDR также поддерживает grammatical selection.
{
gender,
select,
male {Он}
female {Она}
other {Они}
}
FormatJS использует эти конструкции через ICU MessageFormat.
CLDR содержит шаблоны относительного времени.
intl.formatRelativeTime(-1, 'day')
Для английского:
1 day ago
Для русского:
1 день назад
Для французского:
il y a 1 jour
CLDR описывает:
intl.formatNumber(5, {
style: 'unit',
unit: 'kilometer'
})
Для английского:
5 km
Для русского:
5 км
CLDR содержит правила соединения списков.
new Intl.ListFormat('en').format([
'JavaScript',
'TypeScript',
'Rust'
])
Результат:
JavaScript, TypeScript, and Rust
Для русского:
JavaScript, TypeScript и Rust
CLDR хранит локализованные имена:
new Intl.DisplayNames(['ru'], {
type: 'region'
}).of('US')
Результат:
Соединённые Штаты
CLDR поддерживает различные numeral systems.
new Intl.NumberFormat('ar-EG').format(123456)
Результат:
١٢٣٬٤٥٦
Используются арабские цифры Unicode.
CLDR содержит информацию о направлении текста.
RTL-языки:
FormatJS сам не управляет layout, однако корректно форматирует текст для RTL-локалей через Unicode bidi algorithm.
Если локаль отсутствует, применяется fallback.
<IntlProvider
locale="fr-CA"
defaultLocale="en"
>
Fallback-цепочка:
fr-CA → fr → en
CLDR определяет inheritance между локалями.
Intl API использует locale negotiation.
navigator.languages
Может вернуть:
['ru-KZ', 'ru', 'en-US']
Далее выбирается наиболее подходящая локаль.
CLDR содержит likely subtags.
Например:
en → en-Latn-US
zh → zh-Hans-CN
sr → sr-Cyrl-RS
Это помогает движкам правильно определять:
CLDR стандартизирует locale identifiers.
Intl.getCanonicalLocales('EN_us')
Результат:
['en-US']
CLDR содержит:
intl.formatDate(new Date(), {
timeZone: 'Europe/Paris',
timeStyle: 'long'
})
BCP 47 поддерживает расширения Unicode.
en-US-u-ca-buddhist
Буддийский календарь.
de-DE-u-nu-latn
Латинские цифры.
ar-EG-u-nu-arab
Арабские цифры.
Старые браузеры могут не поддерживать часть Intl API.
FormatJS предоставляет polyfills:
@formatjs/intl-pluralrules
@formatjs/intl-relativetimeformat
@formatjs/intl-displaynames
Polyfills включают данные CLDR.
Полный набор CLDR очень большой. Поэтому FormatJS позволяет:
import '@formatjs/intl-pluralrules/locale-data/ru'
Для production обычно:
await import(
'@formatjs/intl-relativetimeformat/locale-data/ru'
)
Unicode регулярно выпускает новые версии CLDR.
Обновления включают:
FormatJS периодически синхронизируется с актуальными версиями CLDR.
CLDR не решает:
CLDR отвечает исключительно за стандартизированные локализационные данные.
Частая ошибка — путать ICU и CLDR.
| Система | Назначение |
|---|---|
| CLDR | данные |
| ICU | библиотека обработки |
| Intl API | JavaScript API |
| FormatJS | high-level abstraction |
Некоторые локали могут отсутствовать в среде выполнения.
Минимальные сборки Node могут не содержать full ICU data.
Проверка:
Intl.DateTimeFormat.supportedLocalesOf([
'ru',
'ar',
'zh'
])
Для полноценной интернационализации Node.js часто запускается с full ICU.
Пример:
node --icu-data-dir=node_modules/full-icu
Можно исследовать правила локали напрямую.
new Intl.PluralRules('ru').select(5)
Результат:
many
FormatJS и Intl позволяют определить активную локаль.
new Intl.NumberFormat().resolvedOptions()
Результат:
{
locale: 'ru-RU',
numberingSystem: 'latn',
style: 'decimal'
}
CLDR содержит уникальные правила для:
Японский:
1万
Китайский:
1万
Английский:
10K
Славянские локали особенно зависят от CLDR:
Русский, польский, украинский и чешский используют разные pluralization rules.
Корректная локализация влияет на:
Даже неверный разделитель тысяч может ухудшать восприятие интерфейса.
Практически каждая операция FormatJS использует CLDR косвенно:
| Возможность | Зависимость от CLDR |
|---|---|
formatDate |
шаблоны дат |
formatNumber |
числа и валюты |
formatRelativeTime |
relative patterns |
plural |
plural rules |
DisplayNames |
локализованные названия |
ListFormat |
правила списков |
unit formatting |
единицы измерения |
Без CLDR современная интернационализация JavaScript-приложений была бы невозможна.