API Intl предоставляет встроенные средства
интернационализации в JavaScript-движках и опирается на ICU
(International Components for Unicode). Основная задача — корректное
форматирование чисел, дат, валют, единиц измерения и строк с учётом
локали пользователя без необходимости ручной реализации региональных
правил.
Ключевая особенность заключается в том, что Intl
работает на уровне движка и использует системные или встроенные
локализационные базы, что делает его быстрее и точнее большинства
пользовательских решений.
Любая функция Intl опирается на параметр локали, который
задаётся строкой BCP 47:
ru-RU — русский (Россия)en-US — английский (США)kk-KZ — казахский (Казахстан)tr-TR — турецкий (Турция)При отсутствии явного указания используется локаль среды выполнения:
const locale = navigator.language;
Если локаль недоступна, применяется fallback-механизм, который выбирает наиболее близкую доступную конфигурацию.
Intl.NumberFormat обеспечивает форматирование чисел с
учётом правил конкретной локали.
Основные сценарии:
const formatter = new Intl.NumberFormat('ru-RU');
formatter.format(1234567.89);
// "1 234 567,89"
const currencyFormatter = new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'KZT'
});
currencyFormatter.format(12345.67);
// "12 345,67 ₸"
Особенность валютного форматирования заключается в автоматическом учёте:
const percentFormatter = new Intl.NumberFormat('en-US', {
style: 'percent'
});
percentFormatter.format(0.42);
// "42%"
Форматирование дат в разных регионах существенно отличается.
Intl.DateTimeFormat решает эту задачу без необходимости
ручной обработки.
const dateFormatter = new Intl.DateTimeFormat('ru-RU');
dateFormatter.format(new Date());
// "26.05.2026"
const detailed = new Intl.DateTimeFormat('en-GB', {
dateStyle: 'full',
timeStyle: 'long'
});
detailed.format(new Date());
// "Tuesday, 26 May 2026 at 14:35:12 GMT+6"
const parts = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).formatToParts(new Date());
Метод formatToParts позволяет разбирать результат на
структурные элементы, что важно для UI-компонентов с кастомной
версткой.
Сортировка строк в разных языках отличается из-за особенностей алфавитов и правил сравнения.
const collator = new Intl.Collator('ru-RU');
['яблоко', 'ёж', 'арбуз'].sort(collator.compare);
Intl.Collator учитывает:
Дополнительные опции:
new Intl.Collator('en', {
sensitivity: 'base',
numeric: true
});
Vue не предоставляет встроенную систему интернационализации уровня ICU, поэтому Intl API часто используется как базовый слой форматирования в приложениях.
В Vue 3 архитектура локализации обычно строится вокруг реактивного состояния текущей локали и набора форматирующих функций.
В Composition API локаль часто хранится как реактивная переменная:
import { ref, computed } from 'vue';
const locale = ref('ru-RU');
Форматтеры зависят от текущей локали, поэтому их необходимо пересоздавать при изменении языка.
Типовой подход — создание универсального слоя форматирования.
import { computed } from 'vue';
export function useNumberFormat(locale) {
const formatNumber = (value) => {
return new Intl.NumberFormat(locale.value).format(value);
};
return { formatNumber };
}
export function useCurrency(locale, currency) {
const format = (value) => {
return new Intl.NumberFormat(locale.value, {
style: 'currency',
currency
}).format(value);
};
return { format };
}
const { formatNumber } = useNumberFormat(locale);
const price = computed(() => formatNumber(1234567));
Реактивность обеспечивает автоматическое обновление UI при смене локали.
Локаль часто сохраняется в localStorage:
localStorage.setItem('locale', 'ru-RU');
При инициализации приложения:
const locale = ref(localStorage.getItem('locale') || navigator.language);
Изменение локали сопровождается синхронизацией:
watch(locale, (newLocale) => {
localStorage.setItem('locale', newLocale);
});
Объекты Intl.* не являются полностью дешёвыми в
создании, поэтому часто применяются стратегии кеширования.
const cache = new Map();
function getNumberFormatter(locale) {
if (!cache.has(locale)) {
cache.set(locale, new Intl.NumberFormat(locale));
}
return cache.get(locale);
}
В Vue это может быть вынесено в отдельный сервис, чтобы избежать лишних пересозданий при реактивных обновлениях.
function formatDate(locale, date) {
return new Intl.DateTimeFormat(locale.value, {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(date);
}
При изменении локали вычисляемые свойства автоматически пересчитываются:
const formattedDate = computed(() =>
formatDate(locale, new Date())
);
В серверном рендеринге (например, Vue SSR) важно синхронизировать локаль между сервером и клиентом.
Проблемы возникают при различии:
navigator.language (клиент)Accept-Language (сервер)Типовой подход:
Несоответствие приводит к расхождению HTML и предупреждениям гидратации.
Intl.NumberFormat поддерживает форматирование физических
единиц:
const speed = new Intl.NumberFormat('ru-RU', {
style: 'unit',
unit: 'kilometer-per-hour'
});
speed.format(120);
// "120 км/ч"
Поддерживаются единицы:
В экосистеме Vue часто используются библиотеки уровня i18n, однако Intl API остаётся базовым слоем:
Intl — форматированиеТипичная архитектура разделяет:
Форматтер создаётся один раз и не обновляется при смене языка, что приводит к несоответствию UI.
Создание Intl.NumberFormat внутри шаблонов вызывает
лишние вычисления.
Форматирование чисел через строки переводов приводит к ошибкам локализации.
В Vue-приложениях Intl API чаще всего становится частью сервисного слоя:
formatServicelocaleServicedateServiceКаждый сервис инкапсулирует создание форматтеров и их кеширование, обеспечивая предсказуемое поведение интерфейса при смене локали.