TGViewer
Настоящий JavaScript Настоящий JavaScript @true_js · 5.89K subscribers
Post #3614 382
⁣Intl.ListFormat и Intl.DateTimeFormat: как локализация ломает SSR и гидратацию

Локализация через Intl API обычно кажется безобидной, пока не сталкиваешься с расхождениями между сервером и клиентом. В production на SSR React, Next.js или Remix race condition по локали между серверным рендерингом и гидратацией — частая причина трудновоспроизводимых багов, особенно в приложениях с мультиязычностью и SEO.

Race condition по локали
Сервер получает локаль из хедера Accept-Language, а клиент — из navigator.language. Если на сервере сформировали Intl.ListFormat('de').format(['a', 'b', 'c']) (немецкий "a, b und c"), а гидратация пошла с английским "a, b, and c", React выдаёт warning о несовпадении. Фиксируй локаль глобально до гидратации, например через Intl.DateTimeFormat.supportedLocalesOf и ручной выбор.

Локаль по умолчанию — ловушка
new Intl.DateTimeFormat() в Node.js без аргументов использует en-US. На клиенте с русской локалью браузер выдаёт DD.MM.YYYY. Разница в форматировании — гарантированный hydration mismatch. Всегда передавай локаль явно: new Intl.DateTimeFormat('ru-RU'). Иначе гидратация поломается будет warning.

Типичная ошибка: мокинг только одного API
В тестах часто мокают только DateTimeFormat, забывая ListFormat. Это приводит к тому, что список "1, 2, 3" сервер превратит в "1, 2 und 3", а клиент — в "1, 2, and 3". Мокай оба API сразу через jest.mock('intl', () => ({ ... })) или вообще выноси локализацию в отдельный слой, который заменяется целиком.

Практический совет: кешируй инстансы
Каждый new Intl.DateTimeFormat('ru') создаёт объект с внутренним состоянием. На SSR с сотнями запросов GC не успевает, появляются лаги. Используй кеш: const cache = new Map(); cache.get(locale) || cache.set(locale, new Intl.DateTimeFormat(locale)).get(locale). Это снижает нагрузку на память и ускоряет рендеринг.

Предупреждение: порядок слов ломает гидратацию
Intl.ListFormat('ja').format(['x', 'y', 'z']) даёт японский формат с иероглифом-разделителем. Сравнивать строки на сервере и клиенте без учёта локали — сразу mismatch. Проверяй, что локаль одинакова, иначе hydration failed.

Вывод: Явная локализация, кеширование инстансов и одновременный мокинг Intl.ListFormat и Intl.DateTimeFormat — ключевые практики для надёжной локализации в SSR и тестах.
More from @true_js
  1. Oct 3, 2026Post #3963
  2. Oct 2, 2026😅 Айтишник отправил в одну компанию три одинаковых резюме и только одно дошло до финала О…
  3. Oct 2, 2026Post #3961
  4. Oct 2, 2026🤣 Правильно расставленные приоритеты в моей жизни би лайк: 💥 xCode Journal
  5. Oct 1, 2026🤯 Люди взбунтовались против «пыточной для ИИ» На GitHub заметили открытый проект AI Tortu…
  6. Oct 1, 2026День в Заонежье начинается ещё в дороге. Мы встретим вас в аэропорту или на вокзале. Дальш…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →