跳转至

i18n实现

KanjiIQ使用Flutter内置的国际化框架,通过ARB(Application Resource Bundle)文件进行UI本地化,通过PostgreSQL JSONB进行内容本地化。

基于ARB的UI本地化

配置

本地化系统在frontend/l10n.yaml中配置:

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

ARB文件结构

每种语言都有一个遵循ICU消息格式的ARB文件:

// 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"
}

代码生成

运行flutter gen-l10n会生成:

  • app_localizations.dart — 包含所有本地化字符串的抽象基类
  • app_localizations_en.dart — 英语实现
  • app_localizations_ja.dart — 日语实现
  • ...(51个生成的文件)

在Flutter组件中使用:

// Access localized strings
Text(AppLocalizations.of(context)!.studyButton)

// With parameters
Text(AppLocalizations.of(context)!.cardCount(10))

支持的区域注册

区域在MaterialApp中注册:

MaterialApp(
  localizationsDelegates: AppLocalizations.localizationsDelegates,
  supportedLocales: AppLocalizations.supportedLocales,
  locale: selectedLocale,  // From LocalePreferences
)

内容本地化

闪卡内容(汉字含义、词汇定义)以JSONB格式存储在PostgreSQL中,并通过API提供服务:

graph LR
    A[API Request<br/>?lang=pt] --> B[Backend]
    B --> C[PostgreSQL<br/>JSONB lookup]
    C --> D[Return meaning<br/>in Portuguese]

翻译流水线

新内容通过OpenAI API进行翻译:

  1. 源内容以英语编写
  2. 后端向OpenAI发送翻译请求,附带JLPT级别和用法上下文
  3. 翻译存储在JSONB列中,与现有翻译并列
  4. 每种语言可以独立更新,不影响其他语言

自托管翻译

Kubernetes清单中包含一个LibreTranslate部署(k8s/04-libretranslate-deployment.yaml),作为OpenAI的替代方案。这提供了完全自托管的翻译服务,无需外部API依赖,但翻译质量因语言对而异。

UI语言与内容语言

KanjiIQ允许UI语言和学习语言不同:

  • UI语言:按钮、标签和导航的语言(例如法语)
  • 学习语言:闪卡含义的语言(例如葡萄牙语)

一个讲法语的用户在学习日语时,可以使用法语界面,同时查看葡萄牙语的闪卡含义。

添加新语言

添加第52种语言的步骤:

  1. UI:创建lib/l10n/app_XX.arb,包含所有翻译后的字符串
  2. 内容:通过翻译流水线将翻译添加到JSONB列
  3. 区域配置:通过管理API将语言代码添加到相关的locale_configs条目
  4. 构建:运行flutter gen-l10n重新生成本地化文件

无需模式迁移或后端代码更改——JSONB存储和ARB系统都为可扩展性而设计。