Чому локалізація ламає маршрутизацію та метадані
Коли в проєкт додають другу локаль, ламається не переклад, а маршрутизація. З'являється паралельне дерево шляхів, і далі все залежить від того, де саме ви вирішуєте, яку мову показувати: у посереднику запиту, у розкладці чи всередині компонента.
Якщо рішення ухвалюється в трьох місцях одночасно, отримуєте конфлікт маршрутів — частина адрес віддає не ту локаль, частина редиректить по колу, а внутрішні посилання ведуть на мову, якої користувач не вибирав.
Друга типова поломка — дублі canonical. Поки сторінка живе за однією адресою, канонічний тег збирається тривіально.
З мультимовною маршрутизацією та сама сутність доступна за кількома шляхами, і якщо canonical та hreflang формуються в різних шарах, пошуковик бачить конкуруючі версії однієї сторінки.
Виправляється це не правкою шаблону, а єдиним джерелом істини: локаль і шлях мають обчислюватися з одного місця, а альтернативні адреси — генеруватися з того самого списку локалей, що й маршрути.
Третій збій помітний найпізніше: переклад губиться в серверних компонентах. Клієнтська частина мову підхоплює, а серверний рендер віддає текст локалі за замовчуванням — у розмітці виявляється суміш мов, і це б'є і по видачі, і по сприйняттю.
Причина в тому, що словники підвантажуються асинхронно і не завжди доступні на етапі рендера на сервері.
Next-intl налаштування знімає ці проблеми на рівні архітектури: локаль стає частиною сегмента маршруту, словники роздаються через провайдер і доступні і на сервері, і на клієнті, а метадані та альтернативні адреси збираються зі спільного опису локалей. Тоді додавання третьої мови — це рядок у конфігурації, а не ревізія всього дерева шляхів.
Що дає коректна інтернаціоналізація
Коректне налаштування next-intl прибирає головний біль мультимовних сайтів — розсинхрон між маршрутами, словниками та розміткою. Коли локалі, префікси шляхів і заголовок hreflang генеруються з одного джерела, кожна мовна версія отримує власну канонічну адресу.
Пошуковик бачить не дублі, а пов'язані сторінки, і видача перестає «з'їдати» переклади на користь основної мови.
Швидкість додавання мови перестає залежати від розміру проєкту. Новий словник підключається як окремий файл із плоскою структурою ключів, маршрути підхоплюють локаль автоматично, а middleware визначає мову за заголовком запиту та cookie.
На практиці це перетворює запуск мови з багатотижневого проєкту на задачу на кілька днів — без переписування компонентів.
Зростання словників — типова точка відмови. За сотень ключів ручний пошук пропущених перекладів не працює, тому в збірку вбудовується перевірка: відсутній ключ ламає збірку, а не тихо рендериться порожнім рядком на проді.
Такий контроль тримає словники в узгодженому стані, навіть коли над перекладами працює кілька людей паралельно.
Стабільність збірки напряму впливає на релізний цикл. Валідація схем словників на етапі збірки ловить розбіжності в структурі між локалями до деплою, тому оновлення текстів не перетворюється на аварійний відкат.
Ми фіксуємо формат ключів і додаємо перевірку в конвеєр — правки перекладів перестають бути ризиком для продакшену.
У сумі це дає передбачувану пошукову видачу по кожній мові, відсутність дублів в індексі та кероване зростання контенту. Опишіть вашу задачу — повернемося з оцінкою та планом налаштування під ваш стек.
Порівняння підходів до мультимовності
Вибір інструменту мультимовності визначає, скільки ручної роботи залишиться команді після запуску першої мови. На практиці обирають між трьома варіантами: власні словники, стороння бібліотека та next-intl — кожен закриває свій клас завдань і має межі, за якими починає заважати.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Ручні словники | Одна-дві мови, статичний контент, пара десятків рядків | Немає плюралізації, форматування чисел і дат; ключі розходяться між файлами; при зростанні кількості мов з'являються дублі та «забуті» рядки |
| Сторонні бібліотеки | Потрібні екзотичні формати, складні правила відмінювання, нестандартний роутинг | Тягнуть власний шар поверх фреймворку, конфліктують із серверними компонентами, вимагають ручної синхронізації з оновленнями |
| next-intl | Проєкт на Next.js з App Router, кілька мов, серверний рендеринг | Прив'язаний до екосистеми Next.js; для статичного експорту та нестандартних схем роутингу потрібне окреме налаштування |
Ручні словники виграють на старті: нуль залежностей, повний контроль. Проблема проявляється на третій мові, коли з'являються форми з числом і родом, а переклади починають жити в різних гілках коду.
Сторонні бібліотеки закривають складну лінгвістику, але додають шар абстракції між застосунком і фреймворком. Кожне оновлення Next.js перетворюється на перевірку сумісності, а серверні компоненти вимагають обхідних рішень.
next-intl вбудовується в маршрутизацію та рендеринг Next.js напряму: мовний сегмент в URL, словники на сервері, форматування дат і чисел за локаллю. Обмеження одне — інструмент розрахований саме на цей стек, і поза ним його переваги втрачаються.
Як відбувається next-intl налаштування в проєкті
Налаштування інтернаціоналізації в Next.js — це не «підключити бібліотеку», а спроєктувати маршрутизацію, словники та поведінку під час перемикання мови так, щоб жодна мова не ламала SEO і не втрачала контент. Працюємо за етапами, кожен завершується перевірюваним результатом.
- Аудит поточної локалізації. Дивимося, як влаштовані тексти зараз: зашиті в компоненти, лежать у розрізнених файлах або вже винесені у словники. Фіксуємо мови, які реально потрібні, і місця, де контент підставляється динамічно — саме там найчастіше випливають неперекладені рядки.
- Проєктування схеми маршрутів. Визначаємо, чи буде локаль у шляху (
/en/...,/de/...) чи в піддомені, задаємо локаль за замовчуванням і правила редіректів. Від цієї схеми залежить індексація: кожна мова повинна мати власну адресу та коректнийhreflang. - Підключення словників. Розбиваємо переклади за просторами імен — загальні, сторінкові, службові — і налаштовуємо завантаження лише потрібного набору для конкретного маршруту. Так розмір даних, що передаються, не зростає разом із кількістю мов.
- Переклад інтерфейсу та контенту. Замінюємо зашиті рядки на ключі, окремо проходимо формати дат, чисел і множинних форм — вони в різних мовах поводяться по-різному й потребують явних правил, а не шаблонної підстановки.
- Перевірка на всіх мовах. Проганяємо кожен маршрут у кожній локалі: перемикання мови, прямі посилання, редіректи, відсутні ключі. Окремо дивимося, що під час зміни мови користувач залишається на тій самій сторінці, а не падає на головну.
- Передача документації. Віддаємо схему маршрутів, структуру словників, правила додавання нової мови та чек-ліст перевірки. Команда замовника далі розширює локалізацію без нашої участі.
Ключовий принцип: нова мова додається правкою конфігурації та файлу перекладів, а не переписуванням маршрутів. Якщо для запуску локалі потрібно чіпати код сторінок — схема спроєктована неправильно, і ми це виправляємо до передачі.
Артефакти після впровадження інтернаціоналізації
Після впровадження інтернаціоналізації замовник отримує не «працюючий переклад», а комплект, за яким команда зможе додавати мови та правити тексти без нас. Нижче — що саме залишається в репозиторії та в документації.
- Конфігурація маршрутизації та локалей. Файл налаштувань з переліком мов, локаллю за замовчуванням і стратегією префіксів:
/en/catalogпротиcatalogз визначенням мови за заголовком запиту. Окремо зафіксовано поведінку для кореня сайту та для неіснуючих локалей — редірект або сторінка 404. - Схема маршрутів. Таблиця відповідності «публічна адреса → файл сторінки → словник», включно з вкладеними сегментами та динамічними частинами. За нею новий розробник розуміє структуру за хвилини, а не відновлює її за кодом.
- Словники повідомлень. Розкладені за просторами імен: загальні тексти інтерфейсу, сторінки, листи, системні помилки. Формат єдиний для всіх мов, ключі не дублюються між файлами.
- Регламент оновлення перекладів. Описано порядок: хто править вихідну мову, як зміни потрапляють до перекладача, що відбувається з ключами, яких немає в цільовій мові. Зазначено поведінку застосунку за відсутнього перекладу — підстановка вихідного тексту замість порожнього рядка.
- Перевірки цілісності. Автоматичне звіряння словників: розбіжність ключів між мовами та незадіяні рядки виявляються до збірки, а не на проді.
- Документація для редакторів. Інструкція для контент-менеджера: де лежить текст, як додати мову, що не можна змінювати в ключах, щоб не зламати розмітку.
- Схема підключення нових мов. Покроковий список: додати локаль у конфігурацію, створити словник, перевірити маршрути та метадані сторінок. Одна мова додається без правок у компоненти.
Комплект передаємо разом із розбором: показуємо, де що лежить і як перевірити результат локально. Опишіть задачу — повернемося з оцінкою та планом за вашим стеком.
Кейс: прискорення виведення нової мови у 4 рази
Проєкт — маркетплейс послуг з каталогом, особистим кабінетом і потоком користувацьких сповіщень.
Інтерфейс жив трьома мовами, і кожен новий ринок запускався вручну: розробники копіювали сторінки під нову локаль, рядки правили прямо в розмітці, а частина текстів підтягувалася з бази без прив'язки до мови.
На четверту мову пішло три тижні, і майже одразу посипалися помилки локалізації — неперекладені блоки, «з'їхали» дати й числа, листи мовою попереднього користувача.
Окремим болем стали дублі в пошуку. Один і той самий товар відкривався за кількома адресами з різними мовними префіксами, канонічні посилання не проставлялися, і пошукові системи індексували обидві версії. Позиції просідали, а трафік розподілявся між сторінками-клонами замість однієї.
Ми перевели проєкт на next-intl і винесли весь текст у словники за локалями: рядки більше не живуть у розмітці, а підключаються за ключем.
Маршрутизація отримала єдиний префікс мови, для кожної сторінки автоматично формується канонічна адреса й карта мовних версій — дублі закрилися на рівні генерації.
Форматування дат, чисел і валют віддано вбудованим засобам з прив'язкою до локалі, тому регіональні налаштування більше не залежать від того, хто і де відкрив сторінку.
Що змінилося в цифрах
| Метрика | До | Після |
|---|---|---|
| Термін виведення нової мови | 3 тижні | 4 дні |
| Помилки локалізації в релізі | регулярні, десятки правок | поодинокі, ловляться на перевірці |
| Дублі сторінок у пошуку | є за всіма локалями | відсутні |
| Правки тексту без розробника | недоступні | правляться у словнику |
Прискорення в чотири рази дала не сама бібліотека, а порядок, який вона нав'язує: одне джерело тексту, єдина схема адрес, автоматичне форматування.
Додавання мови тепер зводиться до нового словника й одного рядка конфігурації — інженер не переписує сторінки і не ризикує зачепити логіку.
Чим next-intl відрізняється від ручної локалізації?
Ручна локалізація починається з невинного словника в окремому файлі, але живе рівно до першого розходження між мовами.
Далі з'являються ключі, які є в англійській і забуті в німецькій, рядки з підстановкою виду Привіт, {name}, зібрані конкатенацією, і дати, відформатовані вручну під кожен ринок.
Помилки при цьому не падають на збірці — вони спливають у користувача, який бачить порожнє місце замість тексту або англійську фразу посеред німецької сторінки.
next-intl перевертає цю модель: переклади стають типізованим ресурсом, а не набором рядків. Ключі описуються один раз, і звернення до неіснуючого ключа ламає збірку, а не продакшен — забутий переклад у новій мовній гілці ловиться до релізу.
Автопідстановка значень працює через явні параметри, тому порядок слів у різних мовах не доводиться підганяти вручну: шаблон описує сенс, а не позицію.
Окремий біль ручного підходу — відмінювання та форми множини. В українській «1 товар», «2 товари», «5 товарів» — три різні форми, в арабській їх шість, і розбір цього через умови в коді швидко перетворюється на нечитабельну розгалужену логіку.
Бібліотека бере правила зі стандартних даних локалі й сама вибирає потрібну форму за числом, а розробник пише один шаблон замість набору умов.
На рівні підтримки різниця ще помітніша. При ручній локалізації додавання мови — це ревізія всього коду на предмет зашитих рядків, а зміна тексту вимагає синхронної правки кількох файлів.
З next-intl нова мова підключається конфігурацією та файлом перекладів, а структура ключів залишається спільною: правка в одному місці не розходиться по гілках.
Саме тому на проєктах із двома й більше мовами ручна локалізація з часом дорожчає з кожним релізом, а підхід через next-intl — ні.
Технічні сумніви щодо інтернаціоналізації
Розберемо три технічні сумніви, які найчастіше виникають під час налаштування next-intl: швидкість, кешування та робота з динамічним контентом. Нижче — короткі відповіді з механікою, а не загальні слова.
Чи не просяде продуктивність через інтернаціоналізацію?
Ні, якщо повідомлення завантажуються на етапі збірки, а не в рантаймі. Ми тримаємо словники у вигляді статичних модулів і підключаємо їх через серверні компоненти — на клієнт іде лише потрібна мова, без зайвих словників.
Роутинг за локаллю обробляється на рівні middleware, тому редіректи не з'їдають час відгуку. На практиці різниця між одномовною та багатомовною версією вкладається в похибку вимірювання.
Як кешувати сторінки, якщо мова залежить від URL?
Локаль — частина шляху, а отже кожна мовна версія кешується окремо й незалежно. Це дозволяє віддавати статику з кешу на всьому маршруті, не змішуючи мови.
Для сторінок з персоналізацією ми розділяємо статичну оболонку та динамічні дані: оболонка кешується за локаллю, а користувацькі блоки підвантажуються окремо. Так кеш залишається ефективним, а контент — актуальним.
Що робити з динамічним контентом і перекладами з бази?
Рядки, які змінюються без релізу, зберігаємо в базі або в системі керування контентом і підтягуємо за ключем. Статичні тексти інтерфейсу залишаються у словниках, а редаговані — у джерелі даних.
На етапі збірки перевіряємо, що всі ключі перекладені: якщо ключа немає, збірка падає, а не віддає порожнечу в продакшені. Це прибирає клас помилок, коли однією мовою текст є, а іншою — порожній блок.
Чи можна додати нову мову без переписування коду?
Так. Додавання локалі — це новий файл словника і один рядок у конфігурації маршрутів. Компоненти та логіка залишаються недоторканими, бо працюють із ключами, а не з текстом напряму.
Ми заздалегідь закладаємо структуру ключів так, щоб порядок слів і відмінки в різних мовах не ламали верстку.
Якщо залишилися сумніви щодо вашого стеку — опишіть задачу, повернемося з оцінкою та планом.
Обговоримо ваше завдання з локалізації
Щоб повернутися з оцінкою та планом робіт із локалізації, нам потрібен мінімум контексту про ваш застосунок — далі розберемося самі. Опишіть завдання у вільній формі: які мови та регіони потрібні, чи є вже переклади, як влаштована маршрутизація та звідки беруться тексти. Цього достатньо, щоб оцінити обсяг і запропонувати схему.
Що допомагає прискорити старт проєкту:
- Список цільових локалей і пріоритет між ними — від нього залежить структура маршрутів і порядок вичитки.
- Поточний стан текстів: де вони лежать зараз — у розмітці, у базі, у файлах перекладів чи в таблицях у перекладачів.
- Вимоги до форматів дат, чисел, валют і одиниць вимірювання за регіонами — їх зазвичай забувають, а вони ламають інтерфейс найсильніше.
- Наявність готових перекладів і глосарію термінів, щоб не перекладати заново те, що вже узгоджено.
- Доступ до репозиторію та стенду: подивимося, як влаштоване збирання, і запропонуємо схему підключення без переписування застосунку.
- Обмеження за термінами та релізами — під них вибудуємо порядок робіт, щоб локалізація не блокувала поточні завдання.
Ми працюємо з інтернаціоналізацією на рівні архітектури: тексти виносяться з коду, маршрути отримують мовний префікс, а словники підключаються так, щоб додавання нової локалі не вимагало правок у компонентах. Це дозволяє запускати мови по одній, а не чекати повного перекладу всіх розділів.
Опишіть завдання — повернемося з оцінкою, планом робіт і пропозицією щодо термінів. Якщо зручно, додайте посилання на застосунок або скриншоти ключових екранів: так оцінка буде точнішою.







