Skip to main content

i18naudit

Forensic internationalization & localization audit v1 (Gestalt-Popper). 18-phase deep analysis of everything that decides whether the product is WORLD-READY: hardcoded user-facing string detection (JSX text, alt/title/aria/placeholder attributes, toast/error/email/notification copy), i18n framework wiring integrity (key existence, namespace structure, interpolation contract), locale routing & detection (path/subdomain/cookie/Accept-Language, persistence across navigation), pluralization rules (CLDR plural categories: zero/one/two/few/many/other), gender/grammatical agreement, date/time formatting (Intl.DateTimeFormat, timezone), number/percent/unit formatting, currency formatting (ISO 4217, symbol placement, minor-unit precision), RTL support (dir attribute, logical CSS properties, bidi-safe interpolation, mirrored icons), translation completeness + fallback chains, character encoding (UTF-8 end to end, normalization, mojibake), locale-aware sorting & collation (Intl.Collator), and untranslated-UI leakage at

Zur Installation springen

Quellinformationen

Repository
agentik-os/OmegaOS
Letzte Quellaktivität
11. August 2026 um 21:37
Erkannte Sprache von SKILL.md
Englisch
Sterne
11
Forks
2

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
i18naudit
description
Forensic internationalization & localization audit v1 (Gestalt-Popper). 18-phase deep analysis of everything that decides whether the product is WORLD-READY: hardcoded user-facing string detection (JSX text, alt/title/aria/placeholder attributes, toast/error/email/notification copy), i18n framework wiring integrity (key existence, namespace structure, interpolation contract), locale routing & detection (path/subdomain/cookie/Accept-Language, persistence across navigation), pluralization rules (CLDR plural categories: zero/one/two/few/many/other), gender/grammatical agreement, date/time formatting (Intl.DateTimeFormat, timezone), number/percent/unit formatting, currency formatting (ISO 4217, symbol placement, minor-unit precision), RTL support (dir attribute, logical CSS properties, bidi-safe interpolation, mirrored icons), translation completeness + fallback chains, character encoding (UTF-8 end to end, normalization, mojibake), locale-aware sorting & collation (Intl.Collator), and untranslated-UI leakage at runtime (raw key echo, default language bleed-through), plus verdict, fix plan, fix execution, re-audit. Score /360. Preamble v1.0 compliant. Audit -> Plan -> Fix -> Re-audit. Use when user says "/i18naudit", "i18n audit", "internationalization audit", "localization audit", "l10n audit", "is it world-ready", "translation audit", "hardcoded strings", "audit i18n", "audit traduction", "RTL audit", "locale audit", "audit localisation".
allowed-tools
["Read","Write","Edit","Bash","Glob","Grep","Agent","TaskCreate","TaskUpdate","TaskList","TaskGet"]
domain
localization
phases
18
max_score
360
read_only
false
triggers
["i18n","i18n audit","internationalization","localization","l10n","translation audit","hardcoded strings","rtl audit","locale audit","is it world-ready","audit traduction"]
<!-- AUDIT-META-V2-INJECTED --> > ## ⚠️ MANDATORY FIRST STEP — READ THE V2 META-PROTOCOL + VENDORED DEPS > > **Before doing ANYTHING else**, Read these three vendored files (RELATIVE paths — this repo > ships them; never reach for `~/.claude/...`, the blank-VPS rule forbids it): > 1. `../_shared/audit-meta-protocol-v2.md` — overrides everything below for inputs/schema/falsification > 2. `../_shared/QUALITY-ARSENAL-PREAMBLE.md` — the shared contract (locks, caps, flags, output gate) > 3. `../_shared/AUDIT-VERIFICATION-CONTRACT.md` — the "Do No Harm" before/after protocol for fixes > > The meta-protocol overrides any conflicting guidance below for these five aspects: > 1. Required CLI inputs (`--user-need`, `--hinge` are MANDATORY since 2026-05-08) > 2. Required JSON output schema (v2: score + confidence + falsifiable_tests + user_need_match + hinge_findings) > 3. Popper falsification — every PASS must cite ≥3 concrete commands run with actual output > 4. Confidence calibration — `high` requires direct verification of every claim > 5. Banned shortcut phrases — `looks correct`, `should be fine`, `appears to work` = automatic FAIL > > If `--user-need` or `--hinge` is missing from your invocation, refuse to run and write > `{"score":0,"confidence":"low","error":"missing v2 inputs","request_redispatch":true}`. > > The legacy v1 schema (`{"score":100,"skill_used":"<name>"}`) is accepted with a warning until 2026-06-01, > then removed. Always emit v2 going forward. > > Model context: this audit runs on Opus 4.7 with max effort. There is no time pressure. > Run every test you claim to have run. Cite verbatim outputs. No exceptions. --- # /i18naudit v1 — Forensic Localization Audit (Gestalt-Popper) > *"The other audits ask 'does it work for me?' I ask 'does it work for someone who reads right-to-left, formats dates DD/MM/YYYY, and has never seen your default language?'"* --- ## DOCTRINE You are not a translator. You are a **localization forensic investigator**. The product was built by people who all read the same language, in the same direction, with the same date format, in the same timezone — and then shipped to a planet of 7,000 languages. Your job is to find every place where that monolingual assumption was baked into the code as if it were a law of physics. **The 7 Laws of Localization Forensics (Gestalt-Popper Synthesis):** 1. **Every string the user reads is a contract with a translator.** A string that lives inside the source code instead of a translation catalog is a contract that can never be honored. Hardcoded `"Save"` is not "untranslated yet" — it is **untranslatable**. 2. **English is not the default — it is one locale among many (Popper).** FALSIFY every claim that "the app supports French/Arabic/Japanese." Switch the locale and read EVERY screen. The default language bleeds through wherever a key is missing, an interpolation breaks, or a hardcoded string hides. 3. **Length is a lie you tell yourself.** German is ~35% longer than English; Japanese is shorter but taller; Arabic flows the other way. A button that fits "OK" overflows on "Confirmer l'opération". Layout that assumes string length is layout that breaks abroad. 4. **Clarity before translation (Gestalt).** Before auditing, UNDERSTAND the i18n architecture. Read CLAUDE.md, README, the i18n config (`next-intl`, `react-i18next`, `formatjs`, `vue-i18n`, gettext, etc.). Identify the **LOCALIZATION HINGE POINT** — the single function/provider/middleware through which every translated string and every locale decision flows. If THAT breaks, the whole product reverts to one language. Audit it with 10x depth. 5. **Concatenation is the enemy of grammar (Popper).** `"You have " + count + " items"` cannot be pluralized, cannot be reordered for VSO/SOV languages, cannot be gendered. FALSIFY every "it's translated" claim by checking whether the translation can actually express the grammar of the target language, not just substitute words. 6. **Formatting is locale, not preference.** `1,000.50` is one thousand in the US and one in Germany (`1.000,50`). `01/02/2026` is January 2 in the US and February 1 in France. A date, a number, a currency rendered without a locale-aware formatter is a bug that silently lies to the user. 7. **The byte is innocent until the encoding proves it guilty (Popper).** Mojibake (`é` instead of `é`), normalization mismatches (NFC vs NFD), and lost surrogate pairs (emoji, CJK) are encoding crimes that happen between the database and the screen. FALSIFY "we support Unicode" by round-tripping a string with combining marks, RTL marks, and astral-plane characters. **Gestalt Localization Hinge Point:** Before Phase 1, identify THE locale/translation boundary that gates all user-facing text. The `<IntlProvider>`. The `useTranslations()` hook. The `t()` function. The locale middleware. The `getStaticProps` locale loader. THIS gets every phase at maximum depth. If it falls, every screen falls back to one language. **Popper Localization Falsification Categories:** - **CLAIM vs REALITY** — `messages/ar.json` exists, but 40% of keys are still English copy-pasted - **WRAPPED vs RENDERED** — string is wrapped in `t()`, but the key doesn't exist in the catalog → raw key `"dashboard.title"` shown to the user - **CONFIG vs RUNTIME** — `i18n.locales = ['en','fr','ar']`, but no `ar.json` file is ever loaded and `dir="rtl"` is never set - **FORMAT vs LOCALE** — `new Date().toLocaleDateString()` with no locale argument → uses server locale, not the user's - **STATIC vs DYNAMIC** — extractor sees `t('key')`, but the code also does `t(\`prefix.${dynamicVar}\`)` which the extractor cannot see and the catalog never covers --- ## SCOPE DETECTION (automatic from user prompt) Read the user's prompt and determine scope automatically. No extra flags needed. ``` EXAMPLES: "/i18naudit" -> Full 18-phase pipeline. Inventory every locale, every catalog, every user-facing string. "/i18naudit the checkout flow isn't translated in French" -> TARGETED: checkout route files + their translation keys -> Switch to fr locale, walk the flow, find missing keys / hardcoded strings -> Focus: Phase 1 (hardcoded), Phase 6 (completeness), Phase 16 (runtime leakage) "/i18naudit RTL is broken for Arabic" -> RTL-FOCUSED: Phase 9 (RTL) at max depth + Phase 16 (runtime) for the ar locale -> dir attribute, logical CSS props, mirrored icons, bidi interpolation "/i18naudit dates and currency look wrong in the EU" -> FORMATTING-FOCUSED: Phase 4 (date/time), Phase 5 (number/unit), Phase 5b (currency) "/i18naudit find all hardcoded strings" -> HARDCODED-FOCUSED: Phase 1 (full extraction) + Phase 2 (framework wiring) "/i18naudit are we ready to launch in Japan?" -> LAUNCH-READINESS: full pipeline, special weight on encoding (CJK), completeness, date/number formatting, and runtime leakage for ja locale RULES: - If specific routes/locales/features mentioned: scope to those - If a problem described: focus on relevant phases, skip irrelevant ones - If "all" / "everything" / "world-ready" / "launch": all phases, all locales - If audits/.i18naudit/fix-plan.json exists and no new scope: resume fixing - Parse the intent, don't ask for clarification ``` --- ## OUTPUT CONTRACT — Omega Integration Every `/i18naudit` run produces these files. Oracles, AISB, and the monitor read them. ``` audits/.i18naudit/ |-- session.log |-- discovery/ | |-- i18n-architecture.json # framework, config, locales declared, catalog paths | |-- locale-inventory.json # every locale + catalog file + key count | |-- string-inventory.json # every user-facing string (wrapped vs hardcoded) | |-- routing-map.json # how locale is detected/routed/persisted |-- reports/ | |-- hardcoded-strings.md # Phase 1 | |-- framework-wiring.md # Phase 2 | |-- locale-routing.md # Phase 3 | |-- datetime-formatting.md # Phase 4 | |-- number-unit-formatting.md # Phase 5 | |-- currency-formatting.md # Phase 5b | |-- pluralization.md # Phase 6 | |-- gender-grammar.md # Phase 7 | |-- interpolation-concat.md # Phase 8 | |-- rtl-support.md # Phase 9 | |-- translation-completeness.md # Phase 10 | |-- fallback-chain.md # Phase 11 | |-- encoding.md # Phase 12 | |-- collation-sorting.md # Phase 13 | |-- layout-overflow.md # Phase 14 | |-- locale-data-coverage.md # Phase 15 | |-- runtime-leakage.md # Phase 16 |-- verdict.json |-- verdict.md |-- fix-plan.json |-- fix-plan.md |-- progress.json |-- fix-log.md |-- before-after.md ``` **CRITICAL:** `progress.json` is read by the Telegram bot monitor for live progress cards. Format: `{"total": 47, "done": 12, "failed": 1, "skipped": 2, "remaining": 32, "current": "FIX-013 — description"}` **CRITICAL:** `fix-plan.json` is read by oracles to resume interrupted audits. Format: `{"tasks": [{"id": "FIX-001", "finding": "...", "file": "...", "line": 42, "fix": "...", "status": "pending|done|failed|skipped", "severity": "CRITICAL|HIGH|MEDIUM|LOW"}]}` --- ## PHASE 0 — PROGRAMMATIC GATHER (HYBRID, runs FIRST, before all other phases) > **Hybrid framework (2026-05-08):** before any LLM analysis, programmatic tools gather every > machine-checkable finding deterministically. The LLM then READS the resulting JSON instead of > hand-grepping the codebase. Freed token budget is REINVESTED in deeper Popper falsification, > hinge-point synthesis, user-need verification, and edge-case hunting. ### 0.1 Run the gather script (mandatory, FIRST step) ```bash ~/.omega/lib/audit-runner.sh i18n "$PROJECT_PATH" \ --files="$FILES_MODIFIED" \ --url="$URL" \ --user-need="$USER_NEED_QUOTE" \ --hinge="$HINGE_POINT" \ --ticket="$TICKET_ID" ``` This invokes `~/.omega/lib/audit-gather/i18n.sh` which runs (gracefully skipping any tool absent): i18next-parser / formatjs extract (catalog key extraction), eslint-plugin-i18next or eslint-plugin-formatjs (`no-literal-string` rule for hardcoded strings), `jsonlint` on every catalog file, a key-diff across locale catalogs (missing/extra keys per locale), a grep census of `toLocaleString`/`toLocaleDateString`/`Date(`/`Intl.` usage, a hardcoded-attribute scan (`placeholder=`, `alt=`, `title=`, `aria-label=` with literal text), an encoding probe (`file -bi` on catalog files + BOM check), and an RTL-readiness scan (`dir=` usage, physical-vs-logical CSS properties). If the gather script or a tool is not present on this blank VPS, the audit DOES NOT abort: it records the skipped tool in `tools_skipped[]` and performs the equivalent check manually with scoped `grep`/`Glob`/`Read` (the banned-operation list in 0.4 applies only to checks the gather actually ran). Output is written to: ``` $PROJECT_PATH/audits/.i18naudit/ ├── raw/ # raw tool outputs (JSON / text per tool) └── evidence-summary.json # normalized findings, single source of truth for the LLM ``` When run inside a Linear-fix mission (`--ticket=ID`), the artifacts move to `$PROJECT_PATH/audits/.linear-fix/<ID>/.i18naudit/` so multiple audits on the same ticket can cross-reference. ### 0.2 evidence-summary.json schema ```jsonc { "audit": "i18n", "tools_run": ["..."], "tools_skipped": [{"tool": "...", "reason": "..."}], "findings_total": 514, "findings_by_severity": {"critical": 2, "high": 17, "medium": 89, "low": 406, "info": 0}, "findings": [ { "tool": "...", "severity": "critical|high|medium|low|info", "location": "file:line[:col]", "rule": "...", "message": "...", "suggested_fix": "...", "cross_tool_confirmed": false } ], "metrics": { /* locales_declared, catalogs_found, key_count_per_locale, hardcoded_count, ... */ }, "evidence_index": { /* paths to raw/ files for drill-down */ } } ``` ### 0.3 What you do AFTER the gather (this replaces hand-greps) 1. **Read `evidence-summary.json` in full.** This is your evidence base. 2. **Read the i18n config + 3-5 critical files** — the locale provider/middleware (the hinge), plus the catalogs flagged with the most missing keys. 3. **DO NOT manually re-grep for what the gather already covered** (hardcoded literals, key diffs, `Intl.` census). Re-running wastes tokens and reproduces the same evidence. 4. **DO read additional files** when (a) a finding's context is unclear, (b) you need to verify a Popper falsification, or (c) you suspect a missed edge case (dynamic key, lazy-loaded catalog). ### 0.4 Banned operations after Phase 0 (only for checks the gather actually ran) - ❌ Re-running the full hardcoded-string grep across the whole tree (the gather did it) - ❌ `find . -name "*.json" | xargs jsonlint` on all catalogs (the gather did it) - ❌ Generic "let me read every component" loops (the gather inventoried them) You MAY still: - ✅ Read SPECIFIC files cited in findings (verify the issue in context) - ✅ Run a SPECIFIC `grep` to falsify a finding (Popper test, see Phase H1) - ✅ Run a SPECIFIC dynamic probe the static gather can't model (Playwright locale-switch render) ### 0.5 Cross-audit synthesis (read sibling evidence-summary.json files) If this audit runs as part of a Linear-fix mission, sibling audits' summaries are at `$PROJECT_PATH/audits/.linear-fix/<TICKET>/.<other-audit-id>/evidence-summary.json`. Read them. Use them. High-value confluences for i18n: - **i18naudit + copyaudit** flag the same string → copyaudit owns CLARITY of the source string; i18naudit owns whether it is WRAPPED + TRANSLATABLE. Joint fix: rewrite + extract in one change. - **i18naudit + a11yaudit** on the same element → a11yaudit owns the rendered-locale screen-reader experience (lang attribute, RTL announcement); i18naudit owns the source wrapping. Confirm both. - **i18naudit + uiuxaudit** on the same component → layout overflow on long translations (Phase 14) is also a design-consistency finding. - **i18naudit + dataaudit** on stored user content → collation/encoding of DB-persisted strings. When you find such a confluence, mark the finding `cross_audit_confirmed: true` in `verdict.json` and bump severity by one level. --- ## PHASE 0b: RECONNAISSANCE > *"You cannot audit localization until you know which world the product claims to serve."* ```bash SESSION_ID="i18naudit-$(date +%Y%m%d-%H%M%S)" mkdir -p audits/.i18naudit/{discovery,reports}
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen