Skip to content

Internationalization / i18n: Externalize hardcoded Chinese strings #8

@shokorey

Description

@shokorey

The codebase contains hardcoded Chinese strings mixed with code logic. This creates several issues:

  1. Localization barrier: Non-Chinese speakers cannot understand error messages
  2. Maintenance difficulty: Changing text requires code changes
  3. Inconsistent messaging: Same message worded differently in various places
  4. No runtime language switching: Language is baked into the build

Identified Hardcoded Strings

In Player.ts

console.error('未设置血量公式')  // "HP formula not set"
console.error('未设置护盾公式')  // "Shield formula not set"

In other files (estimated)

  • Error messages: ~20 occurrences
  • UI labels: ~15 occurrences
  • Log messages: ~10 occurrences

Proposed Solution

1. Create i18n Infrastructure

// src/i18n/index.ts
export interface TranslationKeys {
  // Errors
  'error.formula.hp_not_set': string
  'error.formula.shield_not_set': string
  'error.formula.invalid_syntax': string
  'error.variable.not_found': string

  // Warnings
  'warn.division_by_zero': string
  'warn.overflow_risk': string

  // Info
  'info.player_created': string
  'info.formula_evaluated': string
}

export type Locale = 'en' | 'zh-CN' | 'ja' | 'ko'

export interface I18nConfig {
  defaultLocale: Locale
  fallbackLocale: Locale
  translations: Record<Locale, Partial<TranslationKeys>>
}

2. Translation Files

// src/i18n/locales/en.ts
export const en: TranslationKeys = {
  'error.formula.hp_not_set': 'HP formula is not configured',
  'error.formula.shield_not_set': 'Shield formula is not configured',
  'error.formula.invalid_syntax': 'Invalid formula syntax: {details}',
  'error.variable.not_found': 'Variable "{name}" not found',

  'warn.division_by_zero': 'Division by zero detected in formula',
  'warn.overflow_risk': 'Calculation may overflow',

  'info.player_created': 'Player "{name}" created with ID {id}',
  'info.formula_evaluated': 'Formula evaluated: {formula} = {result}',
}
// src/i18n/locales/zh-CN.ts
export const zhCN: TranslationKeys = {
  'error.formula.hp_not_set': '未设置血量公式',
  'error.formula.shield_not_set': '未设置护盾公式',
  'error.formula.invalid_syntax': '公式语法无效: {details}',
  'error.variable.not_found': '未找到变量 "{name}"',

  'warn.division_by_zero': '检测到除零错误',
  'warn.overflow_risk': '计算可能溢出',

  'info.player_created': '玩家 "{name}" 已创建,ID: {id}',
  'info.formula_evaluated': '公式计算结果: {formula} = {result}',
}

3. Translation Function

// src/i18n/translator.ts
class Translator {
  private locale: Locale
  private translations: Record<Locale, Partial<TranslationKeys>>

  constructor(config: I18nConfig) {
    this.locale = config.defaultLocale
    this.translations = config.translations
  }

  setLocale(locale: Locale): void {
    this.locale = locale
  }

  getLocale(): Locale {
    return this.locale
  }

  t(key: keyof TranslationKeys, params?: Record<string, string | number>): string {
    const translation = this.translations[this.locale]?.[key]
      ?? this.translations['en']?.[key]
      ?? key

    if (!params) return translation

    return Object.entries(params).reduce(
      (str, [key, value]) => str.replace(`{${key}}`, String(value)),
      translation
    )
  }
}

// Singleton instance
export const i18n = new Translator({
  defaultLocale: 'en',
  fallbackLocale: 'en',
  translations: { en, 'zh-CN': zhCN }
})

// Shorthand
export const t = i18n.t.bind(i18n)

4. Integration with fx Singleton

// Configure language
fx.setLocale('zh-CN')

// Get current locale
const locale = fx.getLocale()

// Translate
const message = fx.t('error.formula.hp_not_set')

5. Usage in Code

// Before
console.error('未设置血量公式')

// After
import { t } from '@soonfx/core/i18n'
console.error(t('error.formula.hp_not_set'))

// With parameters
console.error(t('error.variable.not_found', { name: 'ATK' }))
// Output: 'Variable "ATK" not found'

File Structure

src/
└── i18n/
    ├── index.ts           - Exports and types
    ├── translator.ts      - Translation logic
    └── locales/
        ├── en.ts          - English translations
        ├── zh-CN.ts       - Chinese (Simplified)
        ├── zh-TW.ts       - Chinese (Traditional)
        ├── ja.ts          - Japanese (future)
        └── ko.ts          - Korean (future)

Migration Steps

  1. Create i18n infrastructure
  2. Extract all hardcoded strings to en.ts
  3. Create zh-CN.ts with current Chinese strings
  4. Replace hardcoded strings with t() calls
  5. Add locale configuration to fx singleton
  6. Document supported locales
  7. Add contribution guide for new translations

Runtime Language Switching

// User preference
fx.setLocale(getUserPreference())

// Automatic detection
fx.setLocale(detectBrowserLocale())

// Event for UI updates
fx.on('locale:changed', (newLocale) => {
  updateUI()
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions