Код, работающий с датами, числами и строками без использования возможностей Intl API, часто содержит скрытые ошибки, которые проявляются только при смене локали, часового пояса или региона выполнения. На этапе аудита такие участки выявляются как источники нестабильного поведения и несоответствия ожиданиям пользователей в разных окружениях.
Наиболее распространённые проблемы:
toLocaleString() без явного указания
локали и параметровDate.getMonth(),
Date.getDate(), Date.getFullYear()DD.MM.YYYY)Пример фрагмента, часто встречающегося в устаревшем коде:
const date = new Date();
const formatted = date.getDate() + "." + (date.getMonth() + 1) + "." + date.getFullYear();
Такой подход игнорирует локаль, порядок компонентов и особенности календарных систем.
Числовые значения в интерфейсе часто формируются вручную, что приводит к несогласованности отображения. Основные признаки кода, требующего замены:
number.toFixed() для отображения
валютыФрагмент с потенциальной проблемой:
const price = 1234567.89;
const formatted = price.toFixed(2).replace(".", ",");
В разных регионах такой код приводит к конфликту ожиданий пользователей.
Правильная точка аудита — проверка возможности замены на
Intl.NumberFormat:
const formatter = new Intl.NumberFormat("ru-RU", {
style: "currency",
currency: "RUB"
});
formatter.format(1234567.89);
Наиболее критичная зона аудита — обработка дат. Код без
Intl.DateTimeFormat обычно:
Date.toString() или
toISOString() для отображения пользователюПроблемный пример:
const d = new Date();
const output = d.getDate() + "/" + d.getMonth() + "/" + d.getFullYear();
Аудит выявляет такие участки как нарушающие принцип локализации.
Использование форматтера:
const formatter = new Intl.DateTimeFormat("en-GB", {
year: "numeric",
month: "2-digit",
day: "2-digit"
});
formatter.format(new Date());
При проверке кода важно учитывать также наличие временных зон:
new Intl.DateTimeFormat("ru-RU", {
timeZone: "Europe/Moscow",
dateStyle: "long",
timeStyle: "short"
});
Код, использующий Array.sort() без локализованного
сравнения, часто приводит к некорректному порядку в языках с
диакритическими знаками и различной фонетикой.
Проблемный участок:
names.sort();
Аудит выявляет отсутствие Intl.Collator, который
обеспечивает языковую корректность:
const collator = new Intl.Collator("ru", {
sensitivity: "base"
});
names.sort(collator.compare);
Особое внимание уделяется:
В коде без Intl API часто встречаются условные конструкции:
function format(count) {
if (count === 1) return "1 элемент";
if (count > 1 && count < 5) return count + " элемента";
return count + " элементов";
}
Аудит таких фрагментов выявляет жестко закодированную языковую логику.
Замена на Intl.PluralRules отделяет правила языка от
бизнес-логики:
const rules = new Intl.PluralRules("ru");
const form = rules.select(5);
Часто встречается ручная логика вычисления разницы во времени:
const diff = Date.now() - createdAt;
const hours = Math.floor(diff / 3600000);
return hours + " часов назад";
Такие конструкции плохо масштабируются и не учитывают языковые особенности.
Использование Intl.RelativeTimeFormat устраняет
необходимость ручных вычислений строк:
const rtf = new Intl.RelativeTimeFormat("ru", {
numeric: "auto"
});
rtf.format(-5, "minute");
Формирование строк через конкатенацию остаётся распространённой проблемой:
const result = items.join(", ");
Аудит выявляет отсутствие поддержки языковых правил перечислений.
Использование Intl.ListFormat:
const lf = new Intl.ListFormat("ru", {
style: "long",
type: "conjunction"
});
lf.format(["яблоки", "груши", "сливы"]);
В крупных кодовых базах встречается дублирование форматирования:
Типичный антипример:
function formatDateRu(date) { ... }
function formatDateEn(date) { ... }
function formatDateDe(date) { ... }
Аудит таких конструкций направлен на выявление точек консолидации
через Intl.* API вместо множества специализированных
функций.
Частая проблема — создание новых экземпляров Intl-объектов в каждом вызове функции:
function formatPrice(value) {
return new Intl.NumberFormat("ru-RU", {
style: "currency",
currency: "RUB"
}).format(value);
}
При массовых вызовах это приводит к избыточным затратам.
Аудит фиксирует необходимость переиспользования:
const formatter = new Intl.NumberFormat("ru-RU", {
style: "currency",
currency: "RUB"
});
В SSR-приложениях часто выявляется несоответствие между серверной и клиентской локализацией:
Типичный источник:
new Date().toLocaleString();
Аудит требует фиксации локали и параметров через
Intl.DateTimeFormat, чтобы устранить
недетерминированность.
Некоторые среды выполнения могут не поддерживать расширенные возможности Intl без ICU данных. В коде часто встречаются:
toString()Признак проблемного участка:
if (!Intl.RelativeTimeFormat) {
// кастомная реализация
}
Аудит таких мест направлен на унификацию поведения и устранение расхождений между окружениями.
Часто один модуль одновременно содержит:
Такое смешение затрудняет локализацию и усложняет тестирование.
Использование Intl API позволяет выделить слой
форматирования и сделать его изолированным, снижая связность кода и
упрощая дальнейшую миграцию между локалями.