agentleFS
DnsQueenDnsQueen/orcinus-skills/skills/i18n/SKILL.md

i18n

Skill1 starsChanged 6 days agoMITView on GitHub

Internationalize a project: language tags and negotiation, dates/times/time zones, numbers and currency, RTL layout, pluralization and ICU messages, collation, Unicode, and localization testing. Use when adding a language or locale, or when text, dates, numbers, or RTL layout must render correctly. Only invoke via the orcinus router.

47 other projects use a version of this, 2 of them edited.

Adopted by

Most recently taken up by

Used with

Projects with it also use oss-pr, pr-automation and 9 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • CES-LtdSkill

    oss-pr

    Use when creating a pull request, after committing changes, or when user invokes /oss-pr. Covers branch management, quality checks, commit, push, and PR creation.

    Also in 3 projects that use this

  • CES-LtdSkill

    pr-automation

    PR Automation Orchestrator: poll open PRs, check CI, run review, fix, and merge eligible PRs. Use when: (1) Invoked by daemon via scripts/pr-automation.sh, (2) User says "/pr-automation".

    Also in 3 projects that use this

  • volovelySkill

    pr-fix

    This skill should be used when the user asks to "fix PR comments", "address PR feedback", "resolve PR comments", provides a GitHub PR URL with intent to fix, or says "pr-fix". It reads all review comments on a PR, decides which need code fixes vs. replies, makes the fixes, and posts replies — all with explicit user approval before any GitHub action.

    Also in 3 projects that use this

  • GitHubSkill

    state-management

    CoreAI Sandbox's TanStack Query + mock-JSON data layer. USE WHEN: editing data-fetching hooks (`app/hooks/use*.ts`), adding mock data in `app/data/`, or wiring a component to query state.

    Also in 4 projects that use this

  • xfstudioSkill

    graphql

    GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.

    Also in 3 projects that use this

  • MicrosoftSkill

    bump-version

    Bump the VoxelPic version to a user-specified value. USE FOR: setting or updating the project version across all files that embed it. Applies to requests like 'bump version to X.Y.Z', 'set version', or 'update version'.

    Also in 4 projects that use this

  • +2 more from CES-Ltd

The file

We split this skill into the rules it gives an agent

7 rules. 0 are common, 4 are distinctive, and 3 are very specific to this project.

  • 0

    Common

    Most of the 38 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When the language set is ambiguous and the user did not name one, ask before implementing.

    line 29
  2. Very specific:

    If the user narrowed the domains, load only those plus intl-language.md and intl-testing-and-qa.md.

    line 81
  3. Distinctive:

    Search for the defects that indicate a locale-hardcoded codebase.

    line 87
  4. Distinctive:

    Testing: Add the pseudolocale, the lint rules, and the locale matrix so the work cannot regress.

    line 126
  5. Very specific:

    Follow the conventions already in the repository.

    line 128
  6. Very specific:

    Do not introduce a new dependency when the platform formatter covers the need.

    line 130
  7. Distinctive:

    Never claim the work is done without running these.

    line 134

“Common” is measured: kept by at least 6 in 10 of the 38 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Internationalization (i18n)

Make a codebase correct outside a single locale. This skill audits and then implements internationalization across nine domains, each documented in a reference module under references/.

The Scope Contract

The user may narrow the work by naming aspects, languages, or both. Parse the request before doing anything else.

RequestLanguages in scopeDomains in scope
/i18n (bare)Detect from the project; ask if ambiguousAll nine
/i18n I want language just to be english and spanishen, es onlyAll nine
/i18n only fix the date and time handlingCurrent setintl-date-and-time-format.md only
/i18n add Arabic supportExisting plus arAll nine, with RTL and BiDi promoted
/i18n audit only, change nothingDetectAll nine, report without editing

Two rules govern a narrowed request:

  1. A narrowed language set narrows the configuration, not the correctness of the code. If only en and es are requested, do not add RTL stylesheets or Arabic plural rules — but do still use logical CSS properties, locale-aware formatting APIs, and ICU messages, because those cost nothing now and make the next language a configuration change rather than a rewrite.
  2. A narrowed domain set does not excuse breaking a sibling domain. Adding date formatting while leaving hardcoded concatenated strings still produces broken output. Note the out-of-scope defects you observe, report them, and do not fix them unless the user widens the scope.

When the language set is ambiguous and the user did not name one, ask before implementing. Do not guess a target market.

Phase 1 — Reconnaissance

Establish what exists before proposing anything. Never recommend a library the project already uses, and never migrate an existing i18n library without the user asking.

Detect the stack and the existing i18n surface:

ls -a
cat package.json 2>/dev/null | head -60
cat pyproject.toml composer.json Gemfile go.mod 2>/dev/null | head -60

Find an existing i18n implementation before writing one:

grep -rIl --exclude-dir={node_modules,.git,dist,build,vendor} \
  -E "i18next|react-intl|vue-i18n|next-intl|formatjs|intl-messageformat|gettext|babel|lingui|icu|MessageFormat" . | head -30

find . -path ./node_modules -prune -o \
  \( -name "*.po" -o -name "*.xliff" -o -name "*.arb" -o -name "*.ftl" -o -name "messages*.json" -o -name "locales" -o -name "i18n" \) -print 2>/dev/null | head -30

Record these findings — they drive every later decision:

QuestionWhy it matters
What is the runtime? (Node, browser, Python, PHP, JVM, Go, Rust, mobile)Determines whether Intl is available or a library is required
Which i18n library is already present?Extend it; do not replace it
Where do translations live? Which format?Determines the catalog structure
Is there a TMS or a translation vendor in the loop?Constrains the file format and key policy
Is a locale stored per user? Where?Determines the negotiation source
Does the project already store timestamps with a zone?Determines how much date work is a migration
Are there existing locale-specific branches (if (locale === 'en'))?These are the highest-signal defects

Phase 2 — Load Only the Relevant Modules

Load a reference module when its domain is in scope. Read the file in full; each is written to be self-contained.

DomainModuleLoad when
Language tags, locale negotiation, language selectionreferences/intl-language.mdAlways. This is the entry point for every other domain.
Dates, times, time zones, calendarsreferences/intl-date-and-time-format.mdThe project renders, parses, or stores any date or time
Numbers, currency, units, measurementreferences/intl-number-and-currency.mdThe project displays money, counts, percentages, or quantities
Bidirectional text and RTL layoutreferences/intl-bidi.mdAny RTL language is in scope, or the UI uses physical CSS directions
Pluralization, gender, ICU messagesreferences/intl-pluralization.mdAny user-facing string interpolates a count or a variable
Collation, sorting, string comparisonreferences/intl-collation-and-sorting.mdThe project sorts, searches, deduplicates, or compares user text
Unicode text processing and segmentationreferences/intl-text-processing.mdThe project truncates, counts, normalizes, or manipulates strings
Content, assets, cultural adaptationreferences/intl-content-and-assets.mdAlways, for the catalog structure and layout resilience
Localization testing and QAreferences/intl-testing-and-qa.mdAlways. Establishes the gate that prevents regression.

If the user narrowed the domains, load only those plus intl-language.md and intl-testing-and-qa.md. The language module defines the tag vocabulary every other module depends on, and the testing module defines how you prove the work.

Phase 3 — Audit

Produce a findings list before editing. Each finding names a file, a line, the defect, and the concrete fix.

Search for the defects that indicate a locale-hardcoded codebase. These greps are starting points, not a complete audit:

grep -rn --exclude-dir={node_modules,.git,dist,build,vendor} \
  -E "toLocaleDateString\(\)|toLocaleString\(\)|new Date\(.*\)\.getDate\(\)" . | head -40

grep -rn --exclude-dir={node_modules,.git,dist,build,vendor} \
  -E "\.toUpperCase\(\)|\.toLowerCase\(\)" . | head -40

grep -rn --exclude-dir={node_modules,.git,dist,build,vendor} \
  -E "=== *1|=== *0|count *[<>=]+ *1|\$\{count\}" . | head -40

grep -rn --exclude-dir={node_modules,.git,dist,build,vendor} \
  -E "margin-left|margin-right|padding-left|padding-right|text-align: *(left|right)|left:|right:" . | head -40

grep -rn --exclude-dir={node_modules,.git,dist,build,vendor} \
  -E "\.sort\(\)|ORDER BY" . | head -40

Classify each finding by severity, because the user needs to know what to fix first:

SeverityMeaningExamples
CriticalProduces wrong data, not just wrong presentationStoring a local wall-clock time as an instant; parsing a localized number with parseFloat; truncating a string by code unit and corrupting it
HighVisibly broken for a real localeif (count === 1) pluralization; toUpperCase() on Turkish text; sort() on non-ASCII; date rendered in the server's zone
MediumCorrect today, blocks the next languagePhysical CSS properties; concatenated sentence fragments; a hardcoded MM/DD/YYYY format
LowPolish and completenessMissing lang on inline foreign text; no pseudolocale in CI

Phase 4 — Implement

Apply fixes in this order. The order matters because later work depends on earlier decisions.

  1. Locale model. Define how a locale is represented, negotiated, resolved, and persisted. Everything else consumes this.
  2. Catalog structure. Establish the message file layout, key policy, and placeholder syntax before migrating a single string.
  3. String extraction. Replace hardcoded user-facing strings with catalog lookups, including the ones that look safe.
  4. Formatting. Replace hand-rolled date, number, and currency formatting with the platform formatter or the library's.
  5. Pluralization and grammar. Convert every count-dependent string to an ICU plural. Never leave a numeric conditional.
  6. Direction and layout. Introduce dir, logical CSS properties, and bidi isolation where needed.
  7. Sorting and comparison. Replace code-unit comparison with a locale-aware collator.
  8. Testing. Add the pseudolocale, the lint rules, and the locale matrix so the work cannot regress.

Follow the conventions already in the repository. If the project has an AGENTS.md, CLAUDE.md, CONTRIBUTING.md, or a documented i18n policy, that policy wins over any recommendation in these modules. Report the conflict rather than silently overriding it.

Do not introduce a new dependency when the platform formatter covers the need. Intl in JavaScript, ICU in Java and PHP, Babel in Python, and golang.org/x/text in Go all cover far more than most teams assume.

Phase 5 — Verify

Never claim the work is done without running these.

  • The app builds and the existing test suite passes.
  • Every locale in scope renders the audited screens without a fallback to the default language.
  • No raw formatting API remains on a user-facing path (toLocaleDateString() with no locale or options, new Date().toString(), strftime with a hardcoded pattern).
  • No count-dependent string uses a numeric comparison.
  • No toUpperCase()/toLowerCase() remains on a value used for comparison or identity.
  • Sorting of user-visible lists uses a locale-aware collator.
  • Timestamps are stored with an explicit zone or as an instant, and rendered in the viewer's zone.
  • Layout uses logical properties; an RTL locale was rendered if one is in scope.
  • Truncation and character counting respect grapheme clusters.
  • The pseudolocale build runs and surfaces no hardcoded strings.
  • The locale matrix is wired into CI.

Report what you could not verify and why. An unverified claim is worse than a stated gap.

Output

Report back in this shape, trimmed to what is relevant:

## Scope

Languages: en, es — Domains: all nine

## What Exists

Runtime: Node 22 / React 19. Library: react-intl 7. Catalogs: JSON per locale.
Timestamps: stored as UTC epoch ms. Locale source: user profile.

## Findings

| Severity | Location               | Defect                                         | Fix                                                     |
| -------- | ---------------------- | ---------------------------------------------- | ------------------------------------------------------- |
| Critical | src/orders/total.ts:42 | `parseFloat(row.amount)` on a localized string | Parse with the API formatter, keep a raw numeric column |
| High     | src/cart/Cart.tsx:88   | `items.length === 1 ? 'item' : 'items'`        | ICU plural via `<FormattedMessage>`                     |

## Changes Applied

<grouped by domain, naming the files touched>

## Verification

<the checklist above, with the actual result of each>

## Out of Scope / Not Verified

<defects observed but not fixed, and why>

For a change touching many files, publish the report as an Artifact so the team can review it; keep a short summary in the reply.

Common Mistakes

MistakeWhy It BreaksCorrect Approach
Adding a library before checking for oneTwo i18n systems fight over the same stringsDetect first; extend what exists
if (count === 1)Plural rules are per-language; Polish has four categories, Arabic six, Japanese oneUse ICU plural with the CLDR categories
parseFloat(localizedString)German 1.234,56 parses as 1.234 — a silent 1000x errorParse with the locale-aware formatter; store a raw numeric value
toLocaleDateString() with no localeUses the server or CI locale, not the viewer'sPass the resolved locale explicitly
Storing a local wall-clock time as an instantDST transitions corrupt it and it renders wrong in other zonesStore an instant plus an IANA zone, or a zone-free local time when that is the true meaning
margin-left for direction-aware spacingThe layout does not mirror in RTLUse margin-inline-start and friends
str.toUpperCase() for comparisonTurkish dotless ı and German ß break equality and searchUse Intl.Collator with sensitivity: 'accent', or toLocaleUpperCase(locale)
arr.sort() on user textSorts by code unit; Å, é, and Z land in the wrong placesIntl.Collator(locale).compare
Concatenating sentence fragmentsWord order and grammar differ per language; the result is untranslatableOne complete message per unit with named placeholders
Truncating with .substring()Splits grapheme clusters and corrupts emoji, flags, and Indic scriptsIntl.Segmenter with granularity: 'grapheme'
Adding RTL styling only when RTL is requested, but keeping physical CSSThe next language costs a rewriteUse logical properties from the start; it is free
Machine-translating legal or regulatory copyLegally invalid and often wrongFlag it for human translation
Assuming English text lengthGerman and Finnish run 30-40% longer and break fixed layoutsDesign for expansion; test with the pseudolocale

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.