diff --git a/PR_TEST_CHECKLIST.md b/PR_TEST_CHECKLIST.md index dc5b2fa..adbcf38 100644 --- a/PR_TEST_CHECKLIST.md +++ b/PR_TEST_CHECKLIST.md @@ -81,6 +81,23 @@ Test environment: desktop browser, clean localStorage (`localStorage.clear()` be --- +## 9. i18n / locale coverage (English + Spanish) + +| Step | Expected | Pass/Fail | +|------|----------|-----------| +| Switch language to English via the language toggle | All UI strings update to English — no key paths (e.g. `wallet_setup.error_generic`) visible in the UI | | +| On `/login`, reject Freighter connection | English error banner shows a human-readable sentence (not a key path) | | +| On `/login`, trigger popup-blocked error (block pop-ups in browser settings) | English message: "The popup was blocked. Allow pop-ups for this site and try again." | | +| Switch to Spanish, navigate to `/perfil` | NFT mint button shows "Nivel máximo alcanzado" (with accent), not "Nivel maximo alcanzado" | | +| With Spanish active, trigger NFT mint connection error | Toast title shows "Conexión inestable" (with accent), not "Conexion inestable" | | +| Navigate to a non-existent route (e.g. `/xyz`) with Spanish active | 404 page shows "¡Ups! Página no encontrada" (Spanish), not English text | | +| On `/` with wallet disconnected and English active | Banner description reads "Your wallet is not available. Make sure Freighter is installed and unlocked, or use the reconnect button." | | +| Open DevTools console — filter for missing key warnings | No i18next "missing key" warnings for `wallet_setup.*`, `not_found.*`, or `profile.mint_button_max_tier` | | + +--- + +--- + ## Screenshots / clips Attach success and error state screenshots below before merging. diff --git a/src/i18n/config.ts b/src/i18n/config.ts index 67c80f0..87ce3d0 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -4,12 +4,23 @@ * - Default language: Spanish (es) * - Fallback language: Spanish (es) * - Namespace: "translation" (single namespace, flat structure) - * - Missing key behavior: returns the key itself so nothing silently breaks + * - Missing key behavior: returns the key path itself (e.g. "wallet_setup.error_generic") + * so the UI never silently shows a blank string — a visible key path signals a gap. + * + * Fallback chain for a missing key in locale "en": + * 1. Look up key in "en" translation resources. + * 2. If not found, look up key in fallback locale "es". + * 3. If still not found, parseMissingKeyHandler returns the key path as a string. * * To add a new locale: * 1. Create src/i18n/locales/.ts mirroring the es.ts shape * 2. Import it here and add it to the `resources` map * 3. Update the `supportedLngs` array + * + * To add a new key: + * 1. Add the key and English value to en.ts + * 2. Add the key and translated value to es.ts (and any other locales) + * 3. Never rename or delete a key — change only the value to avoid breaking saved references */ import i18n from "i18next"; diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index b96be7f..0416605 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -131,7 +131,7 @@ const en = { deposit_button: "Deposit Earnings", wallet_disconnected_title: "Wallet disconnected", wallet_disconnected_description: - "Freighter is not available. Reconnect your wallet to operate.", + "Your wallet is not available. Make sure Freighter is installed and unlocked, or use the reconnect button.", reconnect: "Reconnect", loading_wallet: "Loading...", welcome_title: "Welcome back!", @@ -251,8 +251,18 @@ const en = { connect_freighter: "Connect with Freighter", freighter_not_detected: "Freighter not detected", freighter_not_detected_description: - "Install the extension or continue with Albedo...", + "Install the extension or continue with Albedo, a web wallet that requires no installation.", + install_freighter_alt: "Install Freighter instead", + install_freighter_link: "Don't have Freighter? Download it here", error_cancelled: "Connection cancelled. You can try again.", + error_popup_blocked: + "The popup was blocked. Allow pop-ups for this site and try again.", + error_wallet_locked: + "Your wallet is locked. Unlock it and try again.", + error_no_network: + "No network connection. Check your internet and try again.", + error_generic: + "Connection error. Make sure your wallet is unlocked and try again.", error_save: "Could not save. Try again.", }, diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index 6226588..b402513 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -331,7 +331,7 @@ const es = { mint_button_signing: "Firmando en Soroban...", mint_button_no_wallet: "Conecta tu wallet para mintear", mint_button_no_balance: "Deposita USDC para evaluar", - mint_button_max_tier: "Nivel maximo alcanzado", + mint_button_max_tier: "Nivel máximo alcanzado", mint_button_already_has: "Ya tienes {{tier}}. Espera al siguiente nivel", max_tier_badge: "Nivel Máximo Alcanzado 💎", @@ -358,20 +358,20 @@ const es = { menu_notifications_detail: "Activadas", menu_help: "Centro de ayuda", menu_logout: "Cerrar sesión", - toast_minted_title: "NFT minteado con exito", + toast_minted_title: "NFT minteado con éxito", toast_minted_description: "Subiste a nivel {{level}}.", - toast_error_connection_title: "Conexion inestable", + toast_error_connection_title: "Conexión inestable", toast_error_connection_description: "No pudimos conectar con la red de Stellar. Intenta nuevamente en unos segundos.", mint_feedback: { - insufficient_level_title: "Aun no alcanzas el siguiente nivel", + insufficient_level_title: "Aún no alcanzas el siguiente nivel", insufficient_level_description: "Sigue ahorrando y vuelve a intentar.", already_minted_title: "Nivel ya minteado", already_minted_description: - "Ya tienes el NFT {{level}}. Sube tu reputacion para mintear el siguiente nivel.", + "Ya tienes el NFT {{level}}. Sube tu reputación para mintear el siguiente nivel.", generic_title: "No se pudo mintear", generic_description: - "No pudimos mintear tu NFT en este momento. Intentalo nuevamente en unos segundos.", + "No pudimos mintear tu NFT en este momento. Inténtalo nuevamente en unos segundos.", }, }, @@ -532,8 +532,8 @@ const es = { // ─── 404 ───────────────────────────────────────────────────────────────────── not_found: { title: "404", - message: "Oops! Page not found", - return_home: "Return to Home", + message: "¡Ups! Página no encontrada", + return_home: "Volver al inicio", }, } as const;