Localization (i18n)
localizationFeatures20 lines
Multi-language text via i18next, with device-locale detection and a typed translation key.
Current — as published in v1.3.2. Written by hand for Localization (i18n), not generated.
The rule
- User-facing text goes through
t('namespace.key')— never a hardcoded English string in a component. A hardcoded string is invisible to every locale except the one the author was looking at. - Interpolation uses single braces —
{name},{count}— instead of i18next's normal default, because this project's own generator claims the double-brace delimiter for its own templates at generation time. The locale JSON files and thei18next.init()config insrc/i18n/index.tswere changed together to avoid the collision. Do not "fix" one without the other — reverting the interpolation delimiter without also reverting every locale file breaks every interpolated string at once, silently (i18next just stops substituting). - Add a key to every locale file at the same time —
en.jsonandes.jsonare meant to stay in lockstep. A key present only inen.jsonsilently falls back to English for every other locale (correct behavior, but worth noticing rather than assuming was intentional). - Plural keys follow i18next's
_one/_othersuffix convention (items_one,items_other) —t('items', { count })picks the right one automatically. Do not hand-roll a plural check with a ternary.
As each tool receives it
The same guidance, in the shape each editor reads. Cursor and Claude Code are written separately by hand; the rest are derived from the Cursor rule.
.cursor/rules/localization.mdc
---
description: Localization (i18n) conventions
globs: ["src/i18n/**/*.ts", "src/i18n/**/*.tsx", "src/i18n/locales/**/*.json"]
alwaysApply: false
---
# Localization (i18n)
- User-facing text goes through `t('namespace.key')` — never a hardcoded
English string in a component. A hardcoded string is invisible to every
locale except the one the author was looking at.
- Interpolation uses single braces — `{name}`, `{count}` — instead of
i18next's normal default, because this project's own generator claims the
double-brace delimiter for its own templates at generation time. The
locale JSON files and the `i18next.init()` config in `src/i18n/index.ts`
were changed together to avoid the collision. Do not "fix" one without the
other — reverting the interpolation delimiter without also reverting every
locale file breaks every interpolated string at once, silently (i18next
just stops substituting).
- Add a key to **every** locale file at the same time — `en.json` and
`es.json` are meant to stay in lockstep. A key present only in `en.json`
silently falls back to English for every other locale (correct behavior,
but worth noticing rather than assuming was intentional).
- Plural keys follow i18next's `_one`/`_other` suffix convention
(`items_one`, `items_other`) — `t('items', { count })` picks the right one
automatically. Do not hand-roll a plural check with a ternary.
What else this module writes
Selecting Localization (i18n) contributes more than a rule file — all of it merged with every other module you pick, with conflicts resolved rather than duplicated.
Dependencies
Depends on the rest of the stack — this module installs different packages depending on what else you select, so there is no single list to show.
Folders
src/i18n/src/i18n/locales/
Put this in your repo
Adds Localization (i18n) to a project this tool generated, without starting over. Files you have hand-edited are left alone.