agentsclimarketplace

I18n next intl

Skill sanctuarynode/skills/skills/i18n-next-intl

Agent skills for stacks conventions

Install
npx -y skills add sanctuarynode/skills --skill i18n-next-intl

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Keep next-intl translations in sync across every locale. Use whenever you add or change a user-facing string — a new t("...") call, a useTranslations namespace, a toast, a button or form-field label, a dialog title/description, or an error message. next-intl ships one JSON message file per locale; touch one locale and the others render the literal {namespace}.{key} at runtime.

SKILL.md

3.5 KB, as published. Nobody here has run it

next-intl: keep every locale in sync

A next-intl app stores one JSON message file per locale — commonly i18n/messages/<locale>.json (en.json, id.json, fr.json, …; your exact path may differ). Every locale file must have the same key tree. A key present in one locale but missing in another renders as the literal {namespace}.{key} string in that locale at runtime.

The rule

Every time you add or modify a translation key, edit it in EVERY locale file in the same change. Never one without the others.

This applies to:

  • Adding a new t("some.key") call in any component
  • Adding a useTranslations("<namespace>") namespace
  • Adding a <FormField> label, placeholder, or description
  • Adding a toast.success(...) / toast.error(...) message
  • Adding a dialog/sheet title or description
  • Any string a user will see

Where keys live

Flat JSON with nested namespaces:

{
  "common": { "save": "...", "cancel": "..." },
  "auth": {
    "welcomeBack": "...",
    "invite": { "title": "...", "completing": "..." }
  },
  "nav": { "dashboard": "...", "settings": "..." }
}

When adding a key:

  1. Pick the namespace path by matching neighboring features — admin pages under admin.<page>, nav labels under nav.*, auth flow under auth.*, etc. Consistency beats cleverness.
  2. Add the same path to every locale file.
  3. Variables use the ICU placeholder convention: "Welcome, {name}" called as t("greet", { name }). Plurals/selects use ICU syntax ({count, plural, one {# item} other {# items}}).

Per-locale translation notes

  • Keep product names, brand names, and proper nouns untranslated; translate the surrounding copy only.
  • Action labels stay short verbs. Match the tone (formal vs casual) already used in the closest sibling keys for that locale.
  • Leave date/number format strings alone — only translate label text around them. For the values themselves, prefer next-intl's useFormatter (format.dateTime, format.number) over hand-formatting.
  • Project-specific glossaries (preferred term for "tenant", "branch", domain nouns) belong in the consuming repo, not here — keep one and link to it so locales stay consistent.

After editing

next-intl doesn't type-check key existence by default. If you wire up a typed-messages augmentation (declare the message shape against next-intl's AppConfig in a global.d.ts), the build flags unknown keys at compile time — set that up for compile-time safety.

Verify nothing is missing

A key present in one locale but not another is a shipping bug. Run the bundled check — it diffs every locale's key tree against the reference (en.json, or the first file) and exits non-zero on any missing/extra key:

scripts/check-locales.sh [MESSAGES_DIR]   # default MESSAGES_DIR: i18n/messages

A clean run is the completion criterion — don't ship on a non-empty diff. To also catch keys referenced in source but never defined, grep them out (grep -roh 't("[^"]\+"' src | sort -u) and eyeball against a locale file — this is a heuristic, since useTranslations("ns") makes t("key") resolve to the full path ns.key.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.