i18n-check
Skill8 starsChanged 49 days agoMITView on GitHub
i18n completeness checker, detects the project's i18n framework (next-intl,
- Pipes a download into a shell
1 other project uses a version of this.
Adopted by
Most recently taken up by
- zhimaAi/ChatClawtheir own version, first seen Oct 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- zhimaAi/ChatClaw★ 307same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository53 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- agent-browserSkill
- anything-to-skillSkill
- ci-generateSkill
- ci-localSkill
- clotho-researchSkill
- codex-imagegenSkill
- create-ruleSkill
- create-skillSkill
- db-migrateSkill
- docker-initSkill
- docs-adrSkill
- docs-checkSkill
- docs-diagramSkill
- docs-initSkill
- docs-rfcSkill
- docs-updateSkill
- env-setupSkill
- find-skillsSkill
- fix-bugSkill
- git-commitSkill
- git-create-prSkill
- gitflowSkill
- git-releaseSkill
- git-syncSkill
- implement-featureSkill
- improve-skillSkill
- inject-docsSkill
- jira-cliSkill
- motion-studioSkill
- optimize-ai-setupSkill
- orchestrateSkill
- oss-launchSkill
- prd-to-issuesSkill
- product-design-specSkill
- product-design-tokensSkill
- product-prdSkill
- project-illustratorSkill
- project-plannerSkill
- refactorSkill
- renderSkill
- review-codeSkill
- review-depsSkill
- review-designSkill
- review-perfSkill
- review-planSkill
- review-securitySkill
- shipSkill
- stopslopSkill
- test-suiteSkill
- vrt-checkSkill
- wtfSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 6 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
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
- Distinctive: line 35
Look for these signals, in order, and stop at the first match:
- Distinctive: line 46
If two signals match (e.g.
- Very specific: line 49
Read references/frameworks.md for the exact default-locale detection and the flatten/diff one-liner for whichever framework you found.
- Distinctive: line 56
Run the bundled script rather than comparing by eye:
- Distinctive: line 77
Do not filter out short or single-word identical matches.
- Very specific: line 88
Default scope is the diff against the base branch (git diff --name-only <base>...HEAD, or git diff --name-only HEAD for uncommitted work): …
- Very specific: line 97
Read references/hardcoded-strings.md for the per-ecosystem patterns (JSX text nodes, Vue templates, Django templates, Rails views) and …
- Distinctive: line 121
If a locale has zero findings across all three categories, say so in one line instead of printing an empty section: don't pad the report.
- Distinctive: line 126
If the user wants the missing keys filled in rather than just reported, insert each missing key into the target locale file at the correct …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
i18n Check
Finds the three ways translations silently rot: a key added to the default locale but never copied to the others (missing), a key copied but never translated (still reads identical to the source), and a key left behind in one locale after being renamed or removed from the default (orphan). Also catches new UI copy that was hardcoded instead of routed through the i18n layer in the first place: the most common way a translation key never gets created.
Step 1: Detect the framework
Look for these signals, in order, and stop at the first match:
| Signal | Framework | Locale file layout |
package.json has next-intl; i18n.ts/i18n/request.ts | next-intl | messages/<locale>.json, nested |
package.json has i18next/react-i18next | i18next | public/locales/<lang>/<ns>.json or src/locales/<lang>.json, nested |
package.json has react-intl | react-intl | lang/<locale>.json, flat, or inline defineMessages (no files) |
package.json has vue-i18n | vue-i18n | src/locales/<lang>.json/.yaml, or <i18n> SFC blocks |
manage.py + locale/<lang>/LC_MESSAGES/*.po | Django gettext | .po catalogs, source strings live in code |
Gemfile + config/locales/*.yml | Rails I18n | YAML keyed by locale at the top level |
If two signals match (e.g. a monorepo with a Rails API and a Vue frontend), run this skill once per app, not once for the whole repo: their locale files don't overlap.
Read references/frameworks.md for the exact default-locale detection and the
flatten/diff one-liner for whichever framework you found. Every framework's diff
reduces to the same three sets (missing / untranslated / orphan) even though the file
format differs.
Step 2: Diff every locale against the default
Run the bundled script rather than comparing by eye:
uv run <skill-dir>/scripts/i18n_diff.py messages/en.json messages/pt-BR.json messages/de.jsonuv runs it with PyYAML resolved from the script header (install uv with
curl -LsSf https://astral.sh/uv/install.sh | sh). JSON-only projects can run it with
plain python3 instead. It takes the default locale file first, then any number of
other locale files (JSON nested or flat, YAML), and prints per locale:
- Missing: key exists in the default locale, absent here.
- Untranslated: key exists in both, and the value is identical to the default locale's value.
- Orphan: key exists here, absent from the default locale (usually a rename or deletion that didn't propagate).
It exits 1 if any key is missing or a locale file can't be read. For .po catalogs and
frameworks with one file per namespace, use references/frameworks.md and run the
script once per namespace pair where the files are JSON or YAML.
Do not filter out short or single-word identical matches. The bug class this skill exists for is exactly that: a one-word label like "Developer" left untranslated because it looked like it might legitimately be the same in both languages. Report every identical match and let a human judge which ones are real bugs: a "smart" filter that suppresses single words or short strings will suppress the real bugs along with the noise. The script already files numbers, URLs and placeholder-only values under a separate "likely fine" bucket instead of "untranslated"; keep that bucket in the report, and move brand names you can identify from context into it too: do not drop them.
Step 3: Scan for hardcoded strings
Default scope is the diff against the base branch (git diff --name-only <base>...HEAD,
or git diff --name-only HEAD for uncommitted work): new UI copy is what actually
ships broken, and scanning the whole codebase on every check is slow and mostly re-finds
the same pre-existing debt. If the user explicitly asks for a full-codebase sweep, do
that instead. In an environment with subagent/Task support, spawn one per top-level
directory to keep the main context clean on a large repo; otherwise run the same grep
patterns directory-by-directory in a single sequential pass: the result is identical,
just slower on very large repos.
Read references/hardcoded-strings.md for the per-ecosystem patterns (JSX text nodes,
Vue templates, Django templates, Rails views) and their exclusions (code identifiers,
console.log/alert calls, strings already wrapped in the project's translate
function).
Step 4: Report by locale
## pt-BR (messages/pt-BR.json, default: messages/en.json)
Missing (2):
- sidebar.developer
- settings.billing.title
Untranslated — identical to en (1):
- sidebar.developer = "Developer"
Orphan — not in en (1):
- sidebar.legacyLabel
## Hardcoded strings (bypass i18n) — 1 finding in changed files
- src/components/Sidebar.tsx:42 <span>Developer</span> (not wrapped in t()/useTranslations)If a locale has zero findings across all three categories, say so in one line instead of printing an empty section: don't pad the report.
Step 5: Scaffold missing keys (only if asked)
If the user wants the missing keys filled in rather than just reported, insert each
missing key into the target locale file at the correct nested path with the value
copied verbatim from the default locale: never invent a translation. This makes the
new key show up as "untranslated" the next time this skill runs, which is the correct
and honest state until a human or translation service actually translates it. For
gettext, add the msgid/msgstr "" pair (empty msgstr is the standard gettext
convention for untranslated). Preserve the file's existing key ordering and formatting
style: read a few existing entries first and match indentation/quote style before
writing.
Then close the loop: re-run the Step 2 command on the same files.
- Missing is empty for every locale (exit code 0).
- The scaffolded keys now appear under "Untranslated", which is the expected state.
- If anything is still missing, fix the insertion and re-run. After 3 rounds, stop and report what is still missing.
Notes
- A locale file that's missing entirely (e.g.
de.jsonnever created) is not a key-level diff: flag it once as "locale file not found" and stop for that locale. - Pluralized keys (
item_one/item_other, ICU{count, plural, ...}) count as one logical key for the missing/orphan check; don't flag a plural form as orphan just because the default locale collapses plural forms differently. - react-intl and other setups that keep source strings inline in code (
defineMessages,<FormattedMessage defaultMessage="...">) have no default-locale file to diff against for missing/untranslated: for those, Step 3's hardcoded-string scan is the primary check, and Step 2 only runs on the non-default locale files that do exist.
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
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.

