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 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.

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.mdchand-written for this tool
.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.