Implementación de i18n¶
KanjiIQ utiliza el framework de internacionalización integrado de Flutter con archivos ARB (Application Resource Bundle) para la localización de UI y JSONB de PostgreSQL para la localización de contenido.
Localización de UI con ARB¶
Configuración¶
El sistema de localización se configura en frontend/l10n.yaml:
Estructura de archivos ARB¶
Cada idioma tiene un archivo ARB siguiendo el formato de mensajes ICU:
// lib/l10n/app_en.arb (template)
{
"@@locale": "en",
"appTitle": "KanjiIQ",
"studyButton": "Start Study",
"selectLanguage": "Select Language",
"selectLevel": "Select JLPT Level",
"cardCount": "{count} cards",
"@cardCount": {
"placeholders": {
"count": { "type": "int" }
}
},
"noConnection": "No internet connection. Using cached data.",
"showAllLanguages": "Show all 51 languages"
}
Generación de código¶
Ejecutar flutter gen-l10n genera:
app_localizations.dart— Clase base abstracta con todas las cadenas localizadasapp_localizations_en.dart— Implementación en inglésapp_localizations_ja.dart— Implementación en japonés- ... (51 archivos generados)
Uso en widgets de Flutter:
// Access localized strings
Text(AppLocalizations.of(context)!.studyButton)
// With parameters
Text(AppLocalizations.of(context)!.cardCount(10))
Registro de locales soportadas¶
Las locales se registran en MaterialApp:
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
locale: selectedLocale, // From LocalePreferences
)
Localización de contenido¶
El contenido de las tarjetas (significados de kanji, definiciones de vocabulario) se almacena como JSONB en PostgreSQL y se sirve a través de la API:
graph LR
A[API Request<br/>?lang=pt] --> B[Backend]
B --> C[PostgreSQL<br/>JSONB lookup]
C --> D[Return meaning<br/>in Portuguese]
Pipeline de traducción¶
El contenido nuevo se traduce a través de la OpenAI API:
- El contenido fuente se escribe en inglés
- El backend envía solicitudes de traducción a OpenAI con contexto sobre el nivel JLPT y uso
- Las traducciones se almacenan en la columna JSONB junto a las traducciones existentes
- Cada idioma puede actualizarse independientemente sin afectar a los demás
Traducción autoalojada
Los manifiestos de Kubernetes incluyen un despliegue de LibreTranslate (k8s/04-libretranslate-deployment.yaml) como alternativa a OpenAI. Esto proporciona traducción completamente autoalojada sin dependencias de APIs externas, aunque la calidad varía según el par de idiomas.
Idioma de UI vs. idioma de contenido¶
KanjiIQ permite que el idioma de la UI y el idioma de estudio sean diferentes:
- Idioma de UI: El idioma de botones, etiquetas y navegación (ej., francés)
- Idioma de estudio: El idioma para los significados de las tarjetas (ej., portugués)
Un usuario francófono que estudia japonés puede tener la interfaz en francés mientras ve los significados de las tarjetas en portugués si lo prefiere.
Añadir un nuevo idioma¶
Para añadir un nuevo (52°) idioma:
- UI: Crear
lib/l10n/app_XX.arbcon todas las cadenas traducidas - Contenido: Añadir traducciones a las columnas JSONB mediante el pipeline de traducción
- Configuración de locale: Añadir el código de idioma a las entradas relevantes de
locale_configsmediante la API de administración - Compilación: Ejecutar
flutter gen-l10npara regenerar los archivos de localización
No se requieren migraciones de esquema ni cambios en el código del backend — el almacenamiento JSONB y el sistema ARB están diseñados para ser extensibles.