Blog details
Blog details

i18next best practices for scalable apps

transglot team

transglot team

i18next is the default choice for i18n in most React and Vue apps for good reason — it is flexible, framework-agnostic at its core, and its JSON-based resource format is simple enough to hand-edit on day one. The problems show up later, once you have real scale: hundreds of keys, plural forms across a dozen locales, and a team that is no longer just you. Here is what actually keeps an i18next setup healthy as it grows.

Namespace early, not "eventually"

A single giant `translation.json` works fine for a prototype and becomes unmanageable fast. Split resources into namespaces that mirror your app's structure — `common`, `auth`, `billing`, `settings` — so a translator (or an AI pass) working on billing copy is not scrolling past five hundred unrelated keys to find the ten that matter.

// locales/en/billing.json
{
  "plan.upgrade.cta": "Upgrade plan",
  "invoice.due_date": "Due {{date}}",
  "seats.remaining": "{{count}} seat left",
  "seats.remaining_plural": "{{count}} seats left"
}
Namespaced resource files instead of one flat file

Namespacing also maps cleanly onto how a translation platform organizes work: keys stay grouped, filtering by "untranslated in billing" is a meaningful question, and reviewers can reason about one feature area at a time instead of the whole app.

Get plural rules right from the start

i18next's `_plural` suffix convention (as in `seats.remaining_plural` above) is straightforward for English, but plural rules are genuinely different across languages — some have two forms, some have six (Arabic's zero/one/two/few/many/other, for example). If your editing workflow only ever shows you the English "singular vs. plural" split, you will ship broken pluralization the moment you add a language with more categories than that.

This is one of the places a dedicated translation tool earns its keep over hand-editing JSON: editing plural forms per CLDR category (not just singular/plural) means a translator working on Arabic or Polish sees exactly the categories that language requires, and nothing gets silently dropped.

Protect your placeholders

Interpolation tokens like `{{count}}`, `{{date}}`, or `{{userName}}` are the single most common thing that breaks in translation — a token gets mistranslated, reordered incorrectly, or dropped entirely, and you find out in production. Two habits help a lot: keep token names in English and semantically meaningful (`{{userName}}`, not `{{x}}`), and if you use AI-assisted first-pass translation, make sure it is running through a pipeline built to preserve tokens structurally rather than treating the string as free text.

// source (en)
"welcome.greeting": "Welcome back, {{userName}}!"

// target (es) — token preserved, not translated or reordered
"welcome.greeting": "¡Bienvenido de nuevo, {{userName}}!"
Token-safe interpolation, before and after translation
How transglot handles this
transglot's AI translation pipeline uses structured JSON output specifically designed to preserve placeholders and tokens, batching roughly 30 keys per chunk through Claude. It is not a substitute for a human pass on customer-facing copy, but it removes the class of bug where a token silently disappears.

Keep your resource files in native i18next JSON — don't detour through CSV

A common anti-pattern: exporting strings to a spreadsheet for translators, then hand-converting back to JSON. Every round trip through CSV is a chance to lose nesting, mangle a plural key, or break a placeholder. Whatever tool manages your translations, favor one that reads and writes i18next's native JSON format directly (flat or nested — i18next supports both), so the file that comes back is the file your app actually loads, with no conversion step in between.

Make "add a language" a cheap operation

The real test of an i18n setup is not the first language — it is the fifth. When you add a new locale, every existing key needs a translation, and manually copying a few hundred keys into a new file is exactly the kind of work that gets postponed and then forgotten. Look for a workflow where adding a locale automatically surfaces (and ideally auto-backfills) the missing keys against your source language, rather than leaving you to diff two JSON files by hand.

Search and filter matter more than they seem to

At a few hundred keys, `Ctrl+F` in your editor is fine. At a few thousand — spread across namespaces and a dozen locales — you need typo-tolerant search (so "invocie" still finds "invoice") and a fast way to filter down to just what is untranslated. This is a small thing until it is the thing standing between you and shipping a release, at which point a virtualized, searchable grid genuinely beats scrolling a JSON file.

None of this requires abandoning i18next itself — it is still the right library for the runtime side of things. What changes as you scale is how you manage the resource files feeding it: namespaced, plural-aware, placeholder-safe, and editable by more than one person without a merge-conflict nightmare.

Share this post

transglot team

transglot team

EngineeringBest practices

Related articles

More guides on localization workflows, terminology, and translation QA.

globe
Get started

Stop hand-editing locale files. Start shipping in every language.

Claude-powered translation, an in-context editor, a glossary and QA workflow, and a CLI, GitHub Action, and REST API — open source, MIT licensed, and self-hostable.