Знаки и нотация

FormatJS опирается на ICU MessageFormat — формализованный язык описания строк интернационализации, в котором текст перестаёт быть простой строкой и становится структурированным выражением с параметрами, условиями и форматированием.

Ключевым элементом нотации выступают фигурные скобки:

{variable}

Фигурные скобки обозначают вставку значения из контекста выполнения. Внутри может находиться идентификатор параметра, путь к значению или выражение форматирования.

Простейшая форма:

Hello, {name}

Здесь name — именованный параметр, подставляемый в строку во время рендеринга.


Идентификаторы и переменные

Имена внутри фигурных скобок подчиняются строгим правилам:

  • допустимы латинские буквы, цифры, символ _
  • имя не должно начинаться с цифры
  • регистр имеет значение

Пример корректной нотации:

{userName}
{item_count}
{price1}

Некорректные формы:

{user-name}
{1price}
{user name}

Каждая переменная интерпретируется как ключ в объекте значений, передаваемом в форматтер.


Экранирование и управляющие символы

Фигурные скобки являются служебными символами, поэтому для их отображения в тексте применяются экранирующие конструкции.

Обычный текст с фигурными скобками:

'{' and '}'

Также используется апостроф как управляющий символ экранирования:

It''s a test

Двойной апостроф интерпретируется как один символ '.

Если необходимо вывести текст, содержащий ICU-синтаксис буквально, используется экранирование:

'{'name'}'

Базовые выражения форматирования

FormatJS расширяет простую подстановку переменных через форматные функции.

Синтаксис:

{value, type, format}

Где:

  • value — переменная
  • type — тип форматирования
  • format — конкретный стиль или правило

Числовое форматирование

Числа форматируются через тип number.

Пример:

{price, number}

С указанием стиля:

{price, number, currency}

Возможные форматы:

  • integer
  • percent
  • currency
  • пользовательские шаблоны через Intl.NumberFormat

Пример с валютой:

{balance, number, currency}

Под капотом используется Intl.NumberFormat, а ICU-нотация лишь задаёт декларативную оболочку.


Форматирование дат и времени

Тип date и time задают правила отображения временных значений.

{createdAt, date}
{createdAt, time}

Стили:

{createdAt, date, short}
{createdAt, date, medium}
{createdAt, date, long}
{createdAt, date, full}

Пример комбинированной логики:

{createdAt, date, long} {createdAt, time, short}

Каждый формат транслируется в Intl.DateTimeFormat.


Множественные формы (plural)

Одним из наиболее сложных элементов нотации является обработка множественного числа.

Синтаксис:

{count, plural, one {1 item} other {# items}}

Структура:

  • count — переменная
  • plural — тип конструкции
  • one, few, many, other — категории языка

Символ # внутри блока заменяется значением переменной.

Пример:

{apples, plural, one {# apple} other {# apples}}

Для языков со сложной морфологией возможно расширение:

{count, plural,
  =0 {no items}
  one {1 item}
  other {# items}
}

Категория =0 обозначает точное совпадение значения.


Условные конструкции select

Конструкция select используется для выбора варианта на основе строкового значения.

{gender, select,
  male {He}
  female {She}
  other {They}
}

Значение gender сопоставляется с ключами внутри блока, после чего выбирается соответствующий текст.

Особенность нотации заключается в строгом соответствии ключей строковым значениям без преобразования типов.


Вложенные структуры

FormatJS допускает вложенные конструкции, что позволяет комбинировать plural и select.

Пример:

{gender, select,
  male {{count, plural, one {He has # item} other {He has # items}}}
  female {{count, plural, one {She has # item} other {She has # items}}}
  other {{count, plural, one {They have # item} other {They have # items}}}
}

Здесь каждая ветка содержит собственную plural-логику, формируя многоуровневую грамматику.


Именованные форматы и описания

FormatJS допускает использование именованных шаблонов через MessageFormat API.

Структура сообщения обычно задаётся через объект:

{
  id: "cart.items",
  defaultMessage: "{count, plural, one {# item} other {# items}}"
}

Поле id выступает ключом локализации, а defaultMessage содержит ICU-нотацию.


Составные выражения

ICU-синтаксис позволяет комбинировать текстовые и форматные элементы в одной строке.

Пример:

Hello {name}, you have {count, plural, other {# messages}} since {date, date, short}

Здесь одновременно используются:

  • подстановка строки
  • множественная форма
  • формат даты

Порядок элементов не фиксирован и зависит от языка локализации.


Специальные символы и ограничения

Внутри ICU-выражений действуют следующие ограничения:

  • фигурные скобки всегда парные
  • вложенность требует полной балансировки
  • запятые разделяют параметры, поэтому внутри текста требуют экранирования
  • пробелы внутри блока значимы для интерпретации текста

Пример некорректного выражения:

{count, plural, one {1 item,} other {# items}}

Запятая в конце блока может нарушить парсинг.


Селекторы с числовыми совпадениями

Помимо стандартных категорий возможно использование точных чисел:

{points, select,
  0 {No points}
  1 {One point}
  other {Many points}
}

Или более формализованная версия plural:

{points, plural,
  =0 {No points}
  =1 {One point}
  other {# points}
}

Символ = фиксирует точное совпадение значения.


Комбинация типов форматирования

ICU позволяет комбинировать форматирование внутри одного выражения:

{amount, number, currency} as of {date, date, medium}

Здесь одновременно применяются:

  • числовой формат валюты
  • формат даты

Такая нотация делает строку декларативной и независимой от логики приложения.


Структурная модель сообщения

MessageFormat в FormatJS интерпретирует строку как дерево выражений:

  • текстовые узлы
  • переменные
  • селекторы
  • plural-ветвления
  • форматные функции

Фактически строка превращается в AST-подобную структуру, где каждый элемент имеет тип и набор параметров.


Поведение пробелов и переносов

Переносы строк внутри ICU-сообщений сохраняются как часть текста:

Hello {name}
Welcome back

При этом внутри фигурных скобок переносы недопустимы и нарушают синтаксис.


Контекстная интерпретация символов

Некоторые символы имеют двойную роль:

  • {} — структура выражения
  • # — подстановка числового значения в plural
  • , — разделитель параметров
  • ' — управляющий символ экранирования

Корректная интерпретация зависит от контекста, в котором символ встречается.


Стабильность нотации в локализациях

ICU MessageFormat обеспечивает единообразие синтаксиса независимо от языка. Одна и та же структура может быть адаптирована под разные грамматические правила без изменения логики выражения.

Пример универсальной формы:

{count, plural, one {# file} other {# files}}

В разных языках интерпретация категорий plural может отличаться, но структура сообщения остаётся неизменной.