# auto_i18n_translation_en_es_strict > Build and maintain a fully synchronized bilingual application (EN / ES) with strict enforcement. - Author: moises-arch - Repository: moises-arch/Skills - Version: 20260121065702 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/moises-arch/Skills - Web: https://mule.run/skillshub/@@moises-arch/Skills~auto_i18n_translation_en_es_strict:20260121065702 --- --- name: auto_i18n_translation_en_es_strict description: Build and maintain a fully synchronized bilingual application (EN / ES) with strict enforcement. --- # 🧠 SKILL — `auto_i18n_translation_en_es_strict` ## PURPOSE Build and maintain a **fully synchronized bilingual application (EN / ES)** where: * English (`en`) is the **single source of truth** * Spanish (`es`) is **automatically generated and kept in sync** * **No deployment is allowed** if translations are missing or inconsistent * The app can **never** ship partially translated UI --- ## SUPPORTED STACKS * React / Next.js / Web * React Native * Flutter * Android (Kotlin) --- ## LANGUAGES & LOCALES ```yaml base_language: en supported_languages: - es locales: - en-US - es-PA ``` --- ## NON-NEGOTIABLE RULES 1. **No hardcoded UI text anywhere** 2. `en` is the **only editable language by developers** 3. `es` is **always generated automatically** 4. Missing or broken translations **FAIL CI** 5. No merge, no deploy without `i18n:check = PASS` --- ## REQUIRED DIRECTORY STRUCTURE ```plaintext /src /i18n index.(ts|js|dart|kt) detectLocale.(...) formatters.(...) translate.(script) check.(script) diff.(script) /locales en.json es.json ``` --- ## SOURCE OF TRUTH CONTRACT * `locales/en.json` * Written by developers * Defines **all keys and ICU rules** * `locales/es.json` * **Never manually edited** * Generated by automation only --- ## KEY RULES * Semantic and stable keys * Namespaced by domain * Never include language in the key * Keys **must not be renamed casually** Example: ```ts t('checkout.payment.confirm') ``` --- ## EXECUTION FLOW (MANDATORY) ### STEP 1 — Detect i18n Changes On every commit / PR: * Compare `en.json` with base branch * Detect: * Added keys * Updated values * Removed keys * Output: `i18n-diff.json` --- ### STEP 2 — Auto-Generate Spanish For every new or updated key: * Generate Spanish translation * Preserve: * ICU MessageFormat * Placeholders (`{count}`, `{name}`) * JSON structure * Remove deleted keys from `es.json` Output: updated `es.json` --- ### STEP 3 — Validate i18n (CI Gate) Run **blocking validation**: FAIL if: * Any key exists in `en.json` but not in `es.json` * ICU syntax is invalid * Placeholder mismatch between languages * Hardcoded strings detected in UI * Orphan keys exist * JSON structure mismatch --- ### STEP 4 — Enforce Merge & Deploy Rules * ❌ PR cannot merge if `i18n:check` fails * ❌ Deploy cannot run if `i18n:check` fails * ✅ Only green builds reach production --- ## REQUIRED SCRIPTS (AGENT MUST CREATE) ### `i18n:diff` * Compares base `en.json` vs current * Outputs: ```json { "added": [], "updated": [], "removed": [] } ``` --- ### `i18n:translate` * Input: `i18n-diff.json` * Output: updated `es.json` * Rules: * Preserve ICU structure * Preserve placeholders * Do not paraphrase logic --- ### `i18n:check` * Deep compare `en.json` vs `es.json` * Validate ICU syntax * Validate placeholders * Validate no missing keys * Exit code ≠ 0 on failure --- ## CI INTEGRATION (MANDATORY) The pipeline **MUST** include: ```plaintext 1. i18n:diff 2. i18n:translate 3. i18n:check ``` If any step fails → stop pipeline. --- ## UI FORMAT & DESIGN RULES * Design for **+30% text expansion** * No fixed-width buttons * Allow wrapping where needed * Never truncate critical copy --- ## ICU MESSAGE FORMAT (REQUIRED) Example — EN: ```json "inbox": { "messages": "{count, plural, one {You have # message} other {You have # messages}}" } ``` Example — ES: ```json "inbox": { "messages": "{count, plural, one {Tienes # mensaje} other {Tienes # mensajes}}" } ``` --- ## FORMATTERS LAYER (MANDATORY) UI must never format directly. Required helpers: ```ts formatDate(date, locale) formatCurrency(amount, currency, locale) formatUnit(value, unit, locale) ``` --- ## TEAM RULES (DO NOT NEGOTIATE) * Devs edit **only `en.json`** * Spanish is always generated * No manual hotfixes in `es.json` * No exceptions in production * If CI is red → fix translations, not workarounds --- ## ACCEPTANCE CRITERIA ✔ Adding a key in `en.json` auto-generates Spanish ✔ CI fails if translations are missing ✔ No mixed-language UI ever reaches production ✔ ICU and placeholders always match ✔ Translation workflow is invisible to developers --- ## SUCCESS DEFINITION The system is correct when: * Language can switch instantly * English and Spanish are always in sync * The team never discusses missing translations again * Production UI looks intentional, not accidental --- ## FINAL RULE (EXECUTIVE MODE) > **“No i18n green = no merge.”**