В работе с адресными данными в интерфейсах, построенных на FormatJS и ICU MessageFormat, ключевую роль играет не только перевод строк, но и корректная структуризация компонентов адреса. Адрес и почтовый индекс являются культурно зависимыми элементами: порядок полей, разделители, формат индекса и даже обязательность отдельных частей варьируются в зависимости от локали.
FormatJS, опираясь на стандарты ICU и встроенные возможности JavaScript Intl, позволяет строить гибкие шаблоны представления адресов и сопутствующих данных без жёсткой привязки к конкретной стране.
Адрес в интернациональных системах рассматривается не как строка, а как набор полей:
Ключевая особенность международной локализации заключается в том, что порядок этих полей и их обязательность меняются.
Например:
FormatJS не навязывает структуру, а позволяет описывать формат через шаблоны ICU MessageFormat.
FormatJS использует синтаксис ICU, где адрес может быть описан как шаблон с переменными.
Пример базового шаблона:
const message = new IntlMessageFormat(
"{country}, {postalCode}, {city}, {street}",
"en"
);
message.format({
country: "Germany",
postalCode: "10115",
city: "Berlin",
street: "Invalidenstraße 117"
});
В реальных приложениях такой линейный формат редко используется напрямую, поскольку порядок элементов зависит от локали.
Более корректный подход — использование различных шаблонов для разных локалей.
const usFormat = new IntlMessageFormat(
"{street}\n{city}, {region} {postalCode}\n{country}",
"en-US"
);
Типичный результат:
1600 Amphitheatre Parkway
Mountain View, CA 94043
United States
const deFormat = new IntlMessageFormat(
"{street}\n{postalCode} {city}\n{country}",
"de-DE"
);
Результат:
Invalidenstraße 117
10115 Berlin
Deutschland
const jpFormat = new IntlMessageFormat(
"〒{postalCode}\n{country}{region}{city}{street}",
"ja-JP"
);
Особенность заключается в плотной конкатенации без пробелов, характерной для японской адресной системы.
Почтовые индексы не являются универсальными: их структура зависит от страны и может включать:
FormatJS не занимается валидацией индексов напрямую, но интегрируется с логикой форматирования и отображения через шаблоны и функции предварительной обработки.
const formatPostalCode = (value, locale) => {
switch (locale) {
case "en-GB":
return value.replace(/^(.{3})(.{3})$/, "$1 $2");
case "ca-CA":
return value.toUpperCase().replace(/^(.{3})(.{3})$/, "$1 $2");
default:
return value;
}
};
Далее результат передаётся в FormatJS как переменная:
const msg = new IntlMessageFormat("{postalCode}", "en-GB");
msg.format({
postalCode: formatPostalCode("SW1A1AA", "en-GB")
});
В React-экосистеме FormatJS часто используется через
react-intl.
import { FormattedMessage } from "react-intl";
<FormattedMessage
id="address.block"
defaultMessage="{street}, {city}, {postalCode}, {country}"
values={{
street: streetValue,
city: cityValue,
postalCode: postalCodeValue,
country: countryValue
}}
/>
Такой подход позволяет динамически подставлять локализованные данные без изменения компонента.
ICU MessageFormat поддерживает условия, что позволяет учитывать наличие или отсутствие компонентов адреса.
const msg = new IntlMessageFormat(
"{street}\n{city}{postalCode, select, undefined {} other {, {postalCode}}}\n{country}",
"en"
);
Такой шаблон исключает отображение пустого почтового индекса, предотвращая появление лишних разделителей.
Перед передачей в FormatJS данные адреса часто нормализуются:
Пример нормализации:
const normalizeAddress = (addr) => ({
street: addr.street.trim(),
city: addr.city.trim(),
region: addr.region?.trim(),
postalCode: addr.postalCode.replace(/\s+/g, ""),
country: addr.country.trim()
});
В крупных приложениях адрес редко хранится в одном шаблоне. Вместо этого используется композиция:
const formatAddress = (addr, formatter) => {
return formatter.format({
street: addr.street,
city: addr.city,
region: addr.region,
postalCode: addr.postalCode,
country: addr.country
});
};
Где formatter выбирается в зависимости от locale:
const getFormatter = (locale) => {
switch (locale) {
case "de-DE":
return deFormat;
case "ja-JP":
return jpFormat;
default:
return usFormat;
}
};
Локализация затрагивает не только порядок элементов, но и визуальные разделители:
FormatJS через ICU-шаблоны позволяет явно контролировать эти различия, не смешивая логику данных и представления.
В динамических формах индекс часто влияет на поведение интерфейса:
FormatJS используется для отображения уже нормализованных значений, тогда как логика проверки выносится в отдельный слой, но синхронизируется с локалью.
FormatJS тесно интегрируется с нативным Intl, особенно в
части:
Intl.DisplayNames (страны и регионы)Intl.Locale (разбор локалей)Intl.NumberFormat (часто используется в индексах с
числовым форматированием)Это позволяет согласовывать отображение адресов с общей локализационной политикой приложения.
Типичные проблемы при неправильной реализации:
FormatJS решает часть этих проблем за счёт шаблонного подхода, но требует корректной подготовки данных на уровне приложения.