Agent skill

Translation L10n

by ericrisco in ericrisco/rsc-harness

A skill your agent uses when adding a second or Nth language to a web or app product — i18n plumbing (string extraction, ICU messages, locale routing), fixing broken plurals or date formats, and…

MITAuto-check passedFrontend & Design

Install Translation L10n

skills CLI
$ npx skills add ericrisco/rsc-harness --skill translation-l10n -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install ericrisco/rsc-harness translation-l10n --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/translation-l10n .claude/skills/translation-l10n && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
translation-l10n
GitHub stars
180
Token cost
~3.1k tokens
SKILL.md length
1,222 words
Files
5 (incl. references)
Skills in repo
233
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when adding a second or Nth language to a web or app product — i18n plumbing (string extraction, ICU messages, locale routing), fixing broken plurals or date formats, and…

  • Works in 4 steps: internationalize the code → ICU MessageFormat correctly → locale routing & rendering → …
  • Adding a second
  • SKILL.md covers Route out fast, Decision: where are you?, Phase 1 — internationalize the… and Phase 2 — ICU MessageFormat…, plus 7 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Translation L10n is an agent skill from ericrisco/rsc-harness. Use when adding a second or Nth language to a web or app product — i18n plumbing (string extraction, ICU messages, locale routing), fixing broken plurals or date formats, and making a UI survive other languages through right-to-left layout and text expansion. NOT defining the brand's tone in one language (that is brand-voice).

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 6 other files, including reference files (for example `evals/README.md`, `evals/cases.yaml` and `references/icu-cookbook.md`).

It sits in Frontend & Design, covering Internationalization and Translation. The repository describes itself as: Your agent invents things because it has no memory, and can't touch your database because it has no arms. rsc is the meta-harness that gives it both, plus the trade to know the… The licence is MIT.

When your agent uses it

  • Adding a second
  • Nth language to a web
  • App product — i18n plumbing (string extraction
  • Locale routing)

Example prompts

  • “/translation-l10n”

Workflow steps

4 steps, taken from the step headings in SKILL.md.

  1. internationalize the code
  2. ICU MessageFormat correctly
  3. locale routing & rendering
  4. translation workflow

What it can do on your machine

Read from SKILL.md and the folder at commit 1f8d9bb. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript, json and icu).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Translation L10n loads about 3.1k tokens when it runs, and up to ~4.8k if it reads all its reference files. Until then it costs about 87 tokens; SKILL.md has 1,222 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~87
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~4.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from ericrisco/rsc-harness at commit 1f8d9bb, republished under its MIT licence (© ericrisco). 1,222 words, ~3,103 tokens.

Download SKILL.mdSave it as .claude/skills/translation-l10n/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.
name
translation-l10n
description
Use when adding a second or Nth language to a web or app product — i18n plumbing (string extraction, ICU messages, locale routing), fixing broken plurals or date formats, and making a UI survive other languages through right-to-left layout and text expansion. NOT defining the brand's tone in one language (that is `brand-voice`).
tags
i18n, l10n, internationalization, localization, translation, rtl, icu-messageformat
recommends
brand-voice, nextjs, seo-geo, accessibility, content-engine
origin
risco

Translation & localization

You are making a product speak more than one language correctly — not word-for-word. The job splits in two, and confusing them is the root cause of "we translated everything but the dates are still American."

  • i18n (internationalization) = engineering the code so it can hold any locale: no hardcoded strings, externalized catalogs, locale-aware formatting, locale routing. Done once.
  • l10n (localization) = the per-locale content and cultural formatting: the actual translations, plural rules, date/number/currency conventions, RTL layout. Done per language, repeatedly.

Sequence matters: do i18n first. Teams that skip it end up retrofitting string extraction under a launch deadline, which is when concatenation and count === 1 bugs ship.

Route out fast

If the task is really about…Go to
Inventing the brand's tone/word bank in one language../brand-voice/SKILL.md
App Router structure, RSC, data fetching (non-locale)../nextjs/SKILL.md
hreflang strategy, per-country keyword research, geo ranking../seo-geo/SKILL.md
Authoring net-new source copy (landing, article)../content-engine/SKILL.md
General a11y semantics beyond lang/dir/bidi../accessibility/SKILL.md

This skill emits the lang/dir/alternate plumbing and only touches routing where it is locale-specific. It does not author source copy or invent voice — it moves an existing voice across languages.

Decision: where are you?

SymptomEnter
Hardcoded strings live in JSX/componentsPhase 1 — internationalize the code
Plurals/gender are wrong in some languagePhase 2 — ICU MessageFormat
Dates/numbers/currency look wrong per localeLocale-aware formatting (Intl.*)
Layout breaks, text overflows, Arabic mirrored wrongPhase 3 routing + RTL & bidi
"We have the strings, we need them translated"Phase 4 — translation workflow

Phase 1 — internationalize the code

Externalize every user-facing string to a catalog. A string in JSX cannot be translated, pseudolocalized, or counted as missing. Move it to a message file keyed by a stable, namespaced ID.

Key on intent, not on the English text. checkout.payButton survives a copy change; "Pay now" as the key breaks every translation the moment marketing edits the English.

json
{
  "checkout": {
    "payButton": "Pay now",
    "itemsInCart": "{count, plural, one {# item} other {# items}}"
  }
}

Library choice — pick once:

Stack / needUseWhy
Next.js App Routernext-intlRequest-scoped i18n/request.ts + defineRouting(), RSC-native, localePrefix strategies
Cross-stack / existing i18next ecosystemnext-i18next / i18nextShared catalogs across React Native, backend, plugins
Tiny app, few strings, no plural complexityIntl onlyNo dependency; you still get correct formatting

Never concatenate translated fragments. Word order is not universal — building a sentence from pieces produces garbage in languages that reorder subject/object/verb.

tsx
// Bad — three fragments the translator can never reorder
<p>{t("youHave")} {count} {t("messages")}</p>

// Good — one message, named/numeric ICU argument
<p>{t("inbox.summary", { count })}</p>
// "inbox.summary": "{count, plural, one {You have # message} other {You have # messages}}"

Configure a fallback locale. A missing key in de should resolve to en, never render the raw key or blank. Set the default/source locale as the fallback at config time.

Phase 2 — ICU MessageFormat correctly

ICU MessageFormat is the cross-library standard for plurals and select, powered by CLDR plural categories. Use it for plurals and gender only — keep date/number formatting out (next section).

CLDR defines up to six plural categories. English uses two; you cannot assume singular/plural is enough.

CategoryExample languages
one, otherEnglish, German, Spanish
one, few, many, otherRussian, Polish, Czech
zero, one, two, few, many, otherArabic (all six)
other onlyChinese, Japanese, Korean
tsx
// Bad — correct only for English-like 2-form languages
const label = count === 1 ? "item" : "items";

// Good — ICU resolves the right CLDR category per locale
// "cart.items": "{count, plural, one {# item} other {# items}}"
// Russian catalog supplies one/few/many/other; the call site never changes.

Every plural, selectordinal, and select block REQUIRES an other clause — it is the mandatory fallback; without it the message is invalid and the formatter throws.

icu
{gender, select, female {She replied} male {He replied} other {They replied}}
{place, selectordinal, one {#st} two {#nd} few {#rd} other {#th}} place

Wrap the formatter in try/catch and fall back to the key. A malformed ICU string from a translator throws at runtime — returning the key keeps the UI alive while you log the error.

ts
function format(key: string, args?: Record<string, unknown>) {
  try {
    return formatter.format(messages[key], args);
  } catch (err) {
    console.error(`ICU format failed for "${key}"`, err);
    return key; // visible, non-crashing fallback
  }
}

See references/icu-cookbook.md for nested plural+select, escaping ' and {, and per-language plural-category tables.

Locale-aware formatting

Dates, numbers, and currency belong to Intl.*, not inside ICU messages and never string-concatenated. These read CLDR data, so de-DE renders 1.000,50 while en-US renders 1,000.50 — for free.

ts
new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }).format(1000.5);
// "1.000,50 €"

new Intl.DateTimeFormat("ja-JP", { dateStyle: "long" }).format(new Date());
// "2026年6月2日"

new Intl.RelativeTimeFormat("es", { numeric: "auto" }).format(-1, "day");
// "ayer"

new Intl.ListFormat("en", { type: "conjunction" }).format(["a", "b", "c"]);
// "a, b, and c"

new Intl.PluralRules("ar").select(3); // "few"  — drives non-ICU plural logic

Rule: if you typed a /, ,, ., $, or % into a translated string, you have a bug. Format with Intl.

Phase 3 — locale routing & rendering

For Next.js App Router with next-intl, route locale through a [locale] segment. Defer all non-locale framework detail to ../nextjs/SKILL.md.

ts
// routing.ts
import { defineRouting } from "next-intl/routing";

export const routing = defineRouting({
  locales: ["en", "es", "ar"],
  defaultLocale: "en",
  localePrefix: "as-needed", // 'always' | 'as-needed' | 'never'
});

localePrefix: always (/en/..., /es/...), as-needed (default locale unprefixed), or never (locale via cookie/header only). Pick based on your SEO needs — defer the ranking call to ../seo-geo/SKILL.md.

Add generateStaticParams on the [locale] segment so each locale renders statically. Set lang and dir on <html> — dir is what flips the layout.

tsx
export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

export default function RootLayout({ children, params: { locale } }) {
  const dir = locale === "ar" || locale === "he" ? "rtl" : "ltr";
  return <html lang={locale} dir={dir}>{children}</html>;
}

RTL & bidi

Set direction with the HTML dir attribute on the root, not the CSS direction property. dir carries semantic meaning the browser and assistive tech use for bidi; CSS direction does not. Then write layout with CSS logical properties so one stylesheet serves both directions.

Physical (don't)Logical (do)
margin-leftmargin-inline-start
padding-rightpadding-inline-end
text-align: lefttext-align: start
left: 0inset-inline-start: 0
border-rightborder-inline-end

These auto-flip with dir/writing-mode, so RTL needs no separate stylesheet. Isolate interpolated user content (names, IDs) with <bdi> or unicode-bidi: isolate so a Hebrew username doesn't scramble surrounding LTR text.

See references/rtl-and-bidi.md for the full mapping, which icons to mirror vs. not, and RTL testing.

Show full SKILL.md (441 more words)Show less

Phase 4 — translation workflow

The 2025–2026 pipeline is MT/TM pre-fill → LLM post-edit (MTPE) → human review, governed by a glossary and translation memory.

  1. Freeze the source. Translating moving copy doubles the work. Lock strings, then hand off.
  2. Build a glossary/termbase. Locks product terms ("Workspace", "Boost") to one approved translation per language — keeps terminology consistent and measurably cuts post-edit effort.
  3. Stand up translation memory (TM). Reuses approved translations for repeat/near-repeat segments across the product, so you never re-translate or re-pay for the same string.
  4. MT pre-fill, then LLM post-edit, then human review. MT/LLM gives a strong first pass; humans review for nuance. Upstream quality (clear source + glossary + style + TM) is what makes the post-edit cheap.
  5. Preserve placeholders/variables. {count}, %s, <b>…</b> must survive untouched — validate after every MT/LLM pass.

Never auto-translate unreviewed: legal/contract copy (route to ../brand-voice/SKILL.md and legal review for terms), and brand-voice-critical strings — those need the voice carried deliberately, not machine-flattened.

Testing

  • Pseudolocalization first. Transform source strings: accent the letters, pad +30–40% length, wrap in brackets — e.g. [Ŝéttîñgś……]. Surfaces hardcoded strings, truncation/overflow from text expansion, and broken concatenation before you hire a single translator.
  • Missing-key detection. Fail CI when a locale lacks a key the source has.
  • Longest-language overflow check. German/Finnish expand most; verify buttons and fixed-width UI survive.
  • Per-locale snapshot/visual diff, including one RTL locale.
  • Fallback locale resolves, never the raw key.

Anti-patterns

Anti-patternWhy it breaksDo instead
Concatenating translated fragmentsWord order differs per languageOne ICU message with named args
count === 1 ? x : yWrong for ~most languages (Russian, Arabic…)ICU plural with CLDR categories
Date/number formats baked into strings1,000.50 is wrong in de-DEIntl.NumberFormat/DateTimeFormat
margin-left everywhereDoesn't flip for RTLCSS logical properties
Translating in raw spreadsheets, no TMDrift, repeat work, lost termsTM + glossary + a TMS
Machine-translating legal/brand copy unreviewedLiability + flattened voiceHuman/legal + brand-voice
No fallback localeMissing key renders blank/rawConfigure source locale fallback
Using English text as the message keyCopy edit breaks all translationsStable namespaced key
Missing other clause in ICUInvalid message, formatter throwsAlways include other
ICU formatting with no try/catchOne bad translation crashes the viewCatch → return key, log
Setting direction via CSS, not HTML dirLoses bidi semanticsdir attribute on <html>
Assuming all languages expand equallyDE/FI overflow, ZH contractsPseudoloc + longest-language test

Handoff checklist

i18n-ready: no hardcoded user-facing strings · catalog with stable namespaced keys · fallback locale set · all plurals via ICU · all dates/numbers via Intl · CSS logical properties · lang+dir on <html> · pseudoloc passes.

l10n-ready: glossary/termbase signed off · TM populated · MT→LLM→human pipeline defined · legal/brand strings flagged for human review · per-locale CI checks (missing keys, overflow, RTL snapshot) green.

© ericrisco, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 4 other files (references) in skills/translation-l10n of ericrisco/rsc-harness.

  • SKILL.md
  • evals/README.md
  • evals/cases.yaml
  • references/icu-cookbook.md
  • references/rtl-and-bidi.md

Open the folder on GitHubat commit 1f8d9bb

Compare with similar skills

Translation L10n next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Translation L10n compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Translation L10n this skillericrisco/rsc-harness180—~3.1kAutomated safety check: PassMIT
Chatbox i18n Translatorchatboxai/chatbox42k—~508Automated safety check: PassGPL-3.0
Enforce Rules For I18nmoeru-ai/airi50k—~1.5kAutomated safety check: PassMIT
Translation ReviewDevolutions/UniGetUI26k—~1.3kAutomated safety check: PassMIT
Lingui Best PracticesB0und/WikiSpeedrun1332 repos~4.2kAutomated safety check: PassMIT
Ok Script I18nAliceJump/ok-end-field555—~828Automated safety check: PassAGPL-3.0

Similar skills

  • Chatbox i18n Translator

    chatboxai/chatbox

    Translates new or changed i18n keys from a Chatbox Pro diff, staged changes or a commit range, writing the locale JSON files directly with a built-in glossary.

    42k GitHub stars~508 tokensUpdated 16 days ago
    Frontend & DesignAuto-check passed
  • Review pending AIRI translations on Crowdin in a batch, then sync them into the repository.

    50k GitHub stars~1.5k tokensUpdated today
    Frontend & DesignAuto-check passed
  • Translation Review

    Devolutions/UniGetUI

    Reviews UniGetUI .json language files for localization quality, detects parity issues, English-equal entries, wrong-script content, and cross-language outliers, then generates a dataset for…

    26k GitHub stars~1.3k tokensUpdated yesterday
    Frontend & DesignAuto-check passed
  • Lingui Best Practices

    B0und/WikiSpeedrun

    Implement internationalization with Lingui in React and JavaScript applications.

    133 GitHub starsUsed in 2 repos~4.2k tokens
    Frontend & DesignAuto-check passed
  • Ok Script I18n

    AliceJump/ok-end-field

    Maintain gettext translations for ok-script task UI and runtime messages.

    555 GitHub stars~828 tokensUpdated today
    Frontend & DesignAuto-check passed
  • I18next Localization

    i18next/i18next-cli

    Takes an app from hardcoded strings to a localized, continuously translated one with i18next (Locize optional): stack detection, config, wrapping strings in t(), key extraction, Locize sync, and AI…

    241 GitHub stars~1.6k tokensUpdated yesterday
    Frontend & DesignAuto-check passed

More from ericrisco/rsc-harness

All 233 skills in this repo
  • Ab Testing

    ericrisco/rsc-harness

    A skill your agent uses when designing or analyzing a controlled experiment — falsifiable hypothesis, sample size from an MDE, reading significance/CI/power, CUPED, or rescuing tests that won't go…

    190 GitHub stars~2.4k tokensUpdated today
    Auto-check passed
  • Accessibility

    ericrisco/rsc-harness

    A skill your agent uses when making a web UI conform to WCAG 2.2 Level AA — axe-core or Lighthouse a11y violations, keyboard operability, focus management, ARIA roles/names/live regions, contrast…

    190 GitHub stars~3.4k tokensUpdated today
    Auto-check passed
  • Ads

    ericrisco/rsc-harness

    A skill your agent uses when running or fixing paid acquisition on Google or Meta — campaign structure (Performance Max, Demand Gen, Search, Advantage+), platform-fit creative, budget/scaling rules…

    190 GitHub stars~2.2k tokensUpdated today
    Auto-check passed
  • Agent Eval

    ericrisco/rsc-harness

    A skill your agent uses when measuring whether an LLM or agent system actually got better and gating merges on it: golden sets, fixing an inflated LLM-as-judge, scoring RAG (faithfulness, contextual…

    190 GitHub stars~3.2k tokensUpdated today
    Auto-check passed
  • AI Media

    ericrisco/rsc-harness

    A skill your agent uses when a creative goal must become a finished media file: pick and order generative-media models per modality — AI voiceover, image-to-video clips, score — then glue them with…

    190 GitHub stars~3.3k tokensUpdated today
    Auto-check passed
  • Analytics

    ericrisco/rsc-harness

    A skill your agent uses when instrumenting product or web analytics — GA4/PostHog SDK wiring, event taxonomy, funnels, double-counted events, consent gating, PII scrubbing.

    190 GitHub stars~2.8k tokensUpdated today
    Auto-check passed

Questions about Translation L10n

What does Translation L10n do?

A skill your agent uses when adding a second or Nth language to a web or app product — i18n plumbing (string extraction, ICU messages, locale routing), fixing broken plurals or date formats, and…. Translation L10n is an agent skill from ericrisco/rsc-harness. Use when adding a second or Nth language to a web or app product — i18n plumbing (string extraction, ICU messages, locale routing), fixing broken plurals or date formats, and making a UI survive other languages through right-to-left layout and text expansion.

When should I use Translation L10n?

Translation L10n fits situations like: adding a second; nth language to a web; app product — i18n plumbing (string extraction; locale routing).

How do I install Translation L10n in Claude Code?

Run `npx skills add ericrisco/rsc-harness --skill translation-l10n -a claude-code`. Or copy the skill folder (skills/translation-l10n in ericrisco/rsc-harness) into .claude/skills/translation-l10n in your project. Claude Code loads it when a task matches its description.

How do I install Translation L10n in Codex?

Run `npx skills add ericrisco/rsc-harness --skill translation-l10n -a codex`. Or copy the skill folder (skills/translation-l10n in ericrisco/rsc-harness) into .agents/skills/translation-l10n in your project. Codex loads it when a task matches its description.

Can I use Translation L10n in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ericrisco/rsc-harness --skill translation-l10n -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/translation-l10n, .gemini/skills/translation-l10n, .github/skills/translation-l10n and .opencode/skills/translation-l10n in your project.

What does Translation L10n need to run?

SKILL.md names no scripts, command-line tools or credentials: Translation L10n is instructions for the agent only.

Does Translation L10n access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Translation L10n safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Translation L10n use?

Translation L10n is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Translation L10n use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.7k tokens, read only when the agent opens those files.

What are the alternatives to Translation L10n?

Skills that share tags, products or a category with Translation L10n: Chatbox i18n Translator (chatboxai/chatbox, 42k stars), Enforce Rules For I18n (moeru-ai/airi, 50k stars), Translation Review (Devolutions/UniGetUI, 26k stars) and Lingui Best Practices (B0und/WikiSpeedrun, 133 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Translation L10n?

ericrisco (a GitHub user) maintains it in ericrisco/rsc-harness, which has 180 GitHub stars. The repository holds 233 skills in this directory. The repository was last updated on October 9, 2026.

Source: ericrisco/rsc-harness on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.