| name | use-react-intl-universal |
| description | Best-practice workflow for building and inspecting high-quality internationalized software with react-intl-universal, react-intl-universal-extract, and this skill's rules/scripts. Use it directly for repositories that use react-intl-universal, and use its language-quality, UI-quality, localized-UI inspection, and locale-synchronization principles as reference guidance for other i18n stacks. |
use-react-intl-universal
Use this skill as the recommended combined practice for repositories that use react-intl-universal: write messages with the library API, extract default messages with react-intl-universal-extract, and follow this skill's workflow, rules, and scripts to keep localized software high quality.
If a repository does not use react-intl-universal, still use the general principles in this skill as reference guidance for agents: preserve language quality, keep localized UI stable, avoid fragmented messages, preserve variable/tag contracts, and keep locale updates reviewable.
Primary Goals
- Help users ship internationalized software that feels native, clear, and trustworthy in every supported locale.
- Maintain high language quality: preserve product intent, user actions, and business meaning through natural target-locale wording, while keeping terminology consistent across modules and workflows.
- Keep localized UI usable in real product layouts, with no text truncation, overflow, overlap, misalignment, or broken component visual integrity, especially in compact controls, tables, forms, dialogs, validation messages, navigation, tabs, segmented controls, button groups, chips, badges, and pagination.
- Make localization changes predictable, reviewable, and safe to evolve over time.
- Reduce future localization cost by producing messages that are extractable, structurally consistent, and safe for translators or agents to update.
Prerequisite
Rich React component interpolation with intl.get requires react-intl-universal@2.14.0 or later.
Main Scenarios
- Add a new business message key.
- Modify the default message for an existing key.
- Inspect a running localized UI from a user-provided page URL.
- Synchronize locale files that the project already supports.
- Keep
.d(defaultMessage), the default locale pack, and existing non-default locale packs consistent.
Daily Development Workflow
When adding or changing user-facing copy, start by inspecting the existing i18n setup. Open Inspect Existing I18n Setup for the detailed checks.
- Discover the project's extraction command and current locale files.
- Update the source
intl.get(key, values).d(defaultMessage) first. Treat .d(defaultMessage) as the source default message that extraction tools should copy into the default locale.
- Keep translatable dynamic values as ICU placeholders, such as
{username}, not JavaScript template interpolation.
- Keep React elements as rich tags, such as
<link>documentation</link>, and keep component props in code.
- Run the project extraction command to regenerate the default locale file.
- Infer or confirm the default locale before editing translated locale files.
- Generate translation tasks only from the default-locale diff. The diff is the source of added and changed keys.
- Generate translation tasks only for existing non-default locale files unless the user explicitly asks to add a new locale.
- Translate non-default locales from task files. Follow Translation Rules. If the user provides glossary, style-guide, product-documentation, screenshot notes, page URLs, or other context assets, include them in the translation tasks. If using subagents, assign work by locale and cap parallel subagents at 5.
- Review returned delta JSON before merging. Check:
- every changed key is covered;
- ICU
{variable} contracts are preserved;
- rich tag
<tag> contracts are preserved;
- non-default translations are not just copied from the default message unless that is intentional;
- static UI-fit length warnings are understood as review prompts, not proof of broken layout;
- translations are natural and match the product/business context;
- English target locales follow the English casing rules in Translation Rules, including Sentence case, Title Case, proper names, acronyms, and all-caps limits.
- Perform a daily static UI-fit review for changed keys whose non-default translation estimated display width is greater than the default message, and for grouped compact controls that may visually break when labels wrap. Inspect the key, source line, JSX/source context, component props,
className, CSS, and layout container before deciding risk. Compact UI such as buttons, tabs, menus, placeholders, table headers, badges, chips, filters, dialog titles, sidebars, and breadcrumbs needs more scrutiny; paragraph/help/docs/FAQ text is usually lower risk. If a segmented control, tab group, button group, chip group, badge group, pagination, table action group, or filter group uses display:flex/, , child buttons/tabs/chips, and border/radius rules such as or /, record a wrapped grouped-control visual-integrity review item. Do not start Browser Use for this daily workflow unless the user asks for UI inspection or a release-quality gate.
Rerun the delta review whenever translation tasks are regenerated; older review reports can have outdated expected item counts.
Prefer the repository's existing extraction script, such as npm run intl:extract. If none exists, use:
npx react-intl-universal-extract \
--cmd extract \
--source-path ./src \
--output-path ./src/locales/en-US.json
It is acceptable for the default locale file to be fully regenerated when the project treats .d() as the source of truth. Do not run extraction into non-default translated locale files.
Do not blindly machine-translate every locale file. Use the default-locale diff to translate only new or changed keys for locales that already exist in the project.
UI Inspection Mode
When the user asks to start a UI inspection or provides a page URL for localization QA, open UI Inspection Mode and use it as the end-to-end orchestration workflow.
Core Rules
-
Rule 1: Use intl.get(key, values).d(defaultMessage) as the source-of-truth text API.
- Rule description: Treat
.d(defaultMessage) as the default locale message. When user-facing copy changes, edit .d(defaultMessage) first, then regenerate the default locale pack from extraction.
- Reason: One source of truth keeps source code, default locale JSON, and translated locale JSON from drifting apart.
- Rule implementation: Use the repository extraction command or
react-intl-universal-extract. If extraction is unavailable, install or configure the extraction tool before continuing; edit the default locale file manually only with explicit user approval. Run verify-locale-export.mjs after extraction when expected locale output matters.
-
Rule 2: Use ICU placeholders for translatable dynamic values.
- Rule description: Write values as
{username}, {count}, and plural/select syntax in .d() messages. Do not use JavaScript template interpolation for values that must be translated.
- Reason: ICU placeholders let each locale reorder values naturally and keep the same behavior whether the message comes from
.d() or a locale pack.
- Rule implementation:
audit-i18n-contract.mjs reports JavaScript template interpolation inside .d(). review-translation-deltas.mjs, audit-changed-locale-keys.mjs, and audit-locale-key.mjs verify placeholder consistency after locale updates.
-
Rule 3: Keep one user-facing sentence in one message key.
- Rule description: Do not split a sentence across several keys just to inject links, badges, styled text, or dynamic values. When replacing hardcoded fragments near dynamic text, pull the surrounding dynamic values into the same ICU message.
- Reason: Split messages prevent translators from changing word order, grammar, punctuation, and emphasis naturally.
- Rule implementation: This is mainly a source-review rule. Use Message Patterns for examples; use
find-hardcoded-cjk.mjs and create-hardcoded-cjk-fix-tasks.mjs when the task includes hardcoded CJK cleanup.
-
Rule 4: Use rich tags for React components and avoid new getHTML usage.
- Rule description: Use rich tag formatters such as
<link>...</link> for inline React elements. Keep component props in code and translatable text in the message. Do not add new usage for React UI.
Skill Resources and Script Flow
references/message-patterns.md: open when writing or reviewing concrete react-intl-universal code examples.
references/inspect-existing-i18n-setup.md: open before editing an unfamiliar repository's source or locale JSON.
references/ui-inspection-mode.md: open when the user asks for a page-level localized UI inspection from a URL.
references/ui-inspection-evidence.md: open before accepting screenshots or editing report.json/report.html; it defines capture admission, claim-level evidence, risk, release, and final-review gates.
references/ui-inspection-report.schema.json: the machine-readable report.json structure consumed by the validator. Do not recreate it as a parallel TypeScript or prose model.
references/ui-inspection-report-wireframe.html: copy-once desktop Chrome shell for the human-readable report. The run-local copy owns styling and interactions.
scripts/init-ui-inspection-report.mjs: creates the run directory, copies the wireframe once, and creates the current report and inspection log.
scripts/inspect-ui-screenshot.mjs: derives immutable image facts from saved pixels.
scripts/collect-ui-fix-evidence.mjs: saves exact Git diff bytes and derives finding- or release-scoped commit, changed-path, and conservative risk-floor evidence.
scripts/run-ui-inspection-validation.mjs: runs one code, locale, test, build, Git, runtime, release, or report command without a shell and preserves raw output as a hashed report artifact.
scripts/validate-ui-inspection-report.mjs: validates report structure, cross-record semantics, assets, Git provenance, release chronology, and review integrity.
scripts/render-ui-inspection-report.mjs: updates only the content region in the validated run-local wireframe.
references/translation-rules.md: open before translating or reviewing non-default locale text.
references/validation-checklist.md: open before final handoff.
references/scripts.md: open before running helper scripts so arguments, output files, and expected evidence are clear.
scripts/: use when locale JSON files are available and deterministic discovery, translation, merge, audit, or handoff evidence is useful.
Recommended evidence flow:
discover-project-i18n.mjs before edits.
verify-locale-export.mjs after extraction/export.
infer-default-locale.mjs when the default locale is not obvious.
create-translation-tasks.mjs --base-ref <ref> for non-default locale work based on the default-locale diff. Add user-provided glossary or product-context files with --context-file.
review-translation-deltas.mjs before merging subagent or human translation results.
create-translation-review-tasks.mjs when delta warnings exist or when a deliberate naturalness/terminology review is useful.
apply-translation-deltas.mjs to merge reviewed translation results.
audit-changed-locale-keys.mjs after merge to verify only the changed keys.
create-i18n-handoff.mjs before reporting the task as done. For normal incremental work, keep the handoff focused on changed keys and translation sync status.
Use full-project scripts only when the user asks for broad cleanup/migration, when preparing a release gate, or when changed-key evidence points to wider debt:
audit-i18n-contract.mjs for a full source/locale contract scan.
find-hardcoded-cjk.mjs and create-hardcoded-cjk-fix-tasks.mjs for hardcoded CJK cleanup.
create-audit-fix-tasks.mjs for large audit remediation queues.
When editing this skill's helper scripts, run self-test.mjs from the script reference before using the scripts in a real repository.
Message Patterns
Open Message Patterns when writing or reviewing concrete code examples.
The reference covers plain ICU values, rich React component interpolation, getHTML migration, shared utility code, plural messages, date/time helpers, number formatting, and TypeScript rich formatter types.