nkds

导航

 

MonkeyCode 国际化实践:如何构建支持多语言的 AI 编程助手

引言

"代码没有国界,但开发者有语言。"

在全球化开发时代,AI 编程助手的国际化能力(Internationalization,简称 i18n)已成为决定其能否服务全球开发者的关键因素。MonkeyCode 作为一款完全开源的 AI 编程助手,从设计之初就将多语言支持作为核心架构目标。

本文将深入探讨 MonkeyCode 的国际化技术实现——从 UI 本地化到多语言代码生成,从 LLM 多语言适配到社区翻译体系。无论你是想为 MonkeyCode 贡献翻译,还是想在自己的项目中借鉴 i18n 方案,都能从中获得实用价值。

🎯 核心信息


一、为什么国际化对 AI 编程助手如此重要?

1.1 全球开发者语言分布

┌─────────────────────────────────────────────────────────────┐
│           全球开发者使用的主要编程语言(按地区)                │
├──────────────┬──────────┬──────────┬────────────────────────┤
│    地区       │  主要语言  │  编程注释惯用│   MonkeyCode 支持状态  │
├──────────────┼──────────┼──────────┼────────────────────────┤
│  中国        │ 中文      │ 中文/英文 │ ✅ 完整支持(母语级)     │
│  日本        │ 日语      │ 日语/英文 │ ✅ 完整支持              │
│  韩国        │ 韩语      │ 韩语/英文 │ ✅ 完整支持              │
│  欧洲(德)  │ 德语      │ 英文/德语 │ ✅ 支持                 │
│  欧洲(法)  │ 法语      │ 英文/法语 │ ✅ 支持                 │
│  欧洲(西)  │ 西班牙语  │ 英文/西语 │ ✅ 支持                 │
│  巴西        │ 葡萄牙语  │ 英文/葡语 │ ✅ 支持                 │
│  俄罗斯      │ 俄语      │ 英文/俄语 │ ✅ 支持                 │
│  阿拉伯世界  │ 阿拉伯语  │ 英文/阿语 │ 🔄 开发中               │
│  印度        │ 印地语等  │ 英文为主  │ ✅ 支持(英文界面+提示)  │
└──────────────┴──────────┴──────────┴────────────────────────┘

1.2 国际化的核心挑战

挑战维度 具体问题 MonkeyCode 解决方案
UI 翻译 界面文案需支持多语言切换 基于 Vue I18n 的动态切换系统
代码注释生成 不同语言习惯不同注释风格 LLM 感知用户语言偏好
错误信息本地化 技术术语翻译准确性 专业术语表 + 社区审核
RTL 语言支持 阿拉伯语/希伯来语的右到左布局 CSS 逻辑属性 + 自动检测
文档多语言 文档需同步维护多版本 Crowdin 集成 + 自动同步
LLM 多语言能力 小语种模型效果不佳 多模型路由 + 翻译增强

二、MonkeyCode 国际化架构

2.1 整体架构图

# monkeycode/i18n/architecture.yaml
i18n_architecture:
  layers:
    - name: "用户界面层"
      components:
        - "Vue I18n (前端框架)"
        - "Go-i18n (后端API)"
        - "CSS Logical Properties (布局)"
      supported_locales: 12
      
    - name: "AI 交互层"
      components:
        - "语言检测器 (Language Detector)"
        - "Prompt 翻译器"
        - "多语言输出格式化器"
      features:
        - "自动识别用户输入语言"
        - "生成对应语言的代码注释"
        - "本地化错误提示"
        
    - name: "内容层"
      components:
        - "Crowdin 翻译平台集成"
        - "术语管理系统 (Terminology DB)"
        - "翻译记忆库 (Translation Memory)"
      workflow:
        - "源语言(中文/英文) → 翻译平台 → 社区翻译 → 审核 → 发布"
        
    - name: "基础设施层"
      components:
        - "Locale 数据包"
        - "字体回退链 (Font Fallback Chain)"
        - "时区/日期格式化"
        - "数字/货币格式化"

2.2 核心代码:Vue I18n 配置

// ===== src/i18n/index.ts =====
import { createI18n } from 'vue-i18n'
import zhCN from './locales/zh-CN.json'
import enUS from './locales/en-US.json'
import jaJP from './locales/ja-JP.json'
import koKR from './locales/ko-KR.json'
import deDE from './locales/de-DE.json'
import frFR from './locales/fr-FR.json'
import esES from './locales/es-ES.json'
import ptBR from './locales/pt-BR.json'
import ruRU from './locales/ru-RU.json'

// 支持的语言列表及其元数据
export const availableLocales = [
  { code: 'zh-CN', name: '简体中文', nativeName: '简体中文', rtl: false },
  { code: 'zh-TW', name: '繁體中文', nativeName: '繁體中文', rtl: false },
  { code: 'en-US', name: 'English', nativeName: 'English', rtl: false },
  { code: 'ja-JP', name: '日本語', nativeName: '日本語', rtl: false },
  { code: 'ko-KR', name: '한국어', nativeName: '한국어', rtl: false },
  { code: 'de-DE', name: 'Deutsch', nativeName: 'Deutsch', rtl: false },
  { code: 'fr-FR', name: 'Français', nativeName: 'Français', rtl: false },
  { code: 'es-ES', name: 'Español', nativeName: 'Español', rtl: false },
  { code: 'pt-BR', name: 'Português (BR)', nativeName: 'Português (Brasil)', rtl: false },
  { code: 'ru-RU', name: 'Русский', nativeName: 'Русский', rtl: false },
  { code: 'ar-SA', name: 'العربية', nativeName: 'العربية', rtl: true },  // RTL
] as const

export type LocaleCode = typeof availableLocales[number]['code']

const i18n = createI18n({
  legacy: false,
  locale: detectUserLocale(),       // 自动检测
  fallbackLocale: 'en-US',          // 回退语言
  messages: {
    'zh-CN': zhCN,
    'en-US': enUS,
    'ja-JP': jaJP,
    'ko-KR': koKR,
    'de-DE': deDE,
    'fr-FR': frFR,
    'es-ES': esES,
    'pt-BR': ptBR,
    'ru-RU': ruRU,
  },
  
  // 数量词复数规则
  pluralizationRules: {
    'zh-CN': () => 0,              // 中文无复数
    'en-US': (choice: number) => choice === 1 ? 0 : 1,
    'ru-RU': (choice: number) => {
      // 俄语复杂复数规则
      const mod10 = choice % 10
      const mod100 = choice % 100
      if (mod10 === 1 && mod100 !== 11) return 0
      if ([2, 3, 4].includes(mod10) && ![12, 13, 14].includes(mod100)) return 1
      return 2
    },
  },
  
  // 日期时间格式化
  datetimeFormats: {
    'zh-CN': {
      short: { year: 'numeric', month: '2-digit', day: '2-digit' },
      long: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },
    },
    'en-US': {
      short: { month: 'short', day: 'numeric', year: 'numeric' },
      long: { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' },
    },
    // ... 其他语言
  },
})

/**
 * 自动检测用户首选语言
 * 优先级:localStorage > 浏览器设置 > 默认(en-US)
 */
function detectUserLocale(): LocaleCode {
  // 1. 检查用户之前的选择
  const saved = localStorage.getItem('monkeycode-locale')
  if (saved && availableLocales.some(l => l.code === saved)) {
    return saved as LocaleCode
  }
  
  // 2. 检测浏览器语言
  const browserLangs = navigator.languages || [navigator.language]
  for (const lang of browserLangs) {
    const matched = availableLocales.find(l => 
      lang.toLowerCase().startsWith(l.code.split('-')[0].toLowerCase())
    )
    if (matched) return matched.code
  }
  
  // 3. 回退到英语
  return 'en-US'
}

export default i18n

2.3 RTL(从右到左)语言支持

/* ===== src/styles/rtl.css ===== */
/* 
 * MonkeyCode RTL 语言支持
 * 使用 CSS Logical Properties 实现自动方向适配
 */

/* 编辑器区域 */
.editor-container {
  /* 使用逻辑属性替代物理属性 */
  padding-inline-start: 16px;   /* 替代 padding-left/right */
  padding-inline-end: 16px;
  margin-block-start: 8px;      /* 替代 margin-top/bottom */
  
  text-align: start;            /* 替代 text-align: left */
}

/* 工具栏按钮组 */
.toolbar-group {
  display: flex;
  flex-direction: row;
  gap: 8px;
  
  /* RTL 模式下自动反转顺序 */
  direction: inherit;           /* 继承父元素 dir 属性 */
}

/* 侧边栏导航 */
.sidebar-nav {
  /* 使用逻辑属性确保 RTL 下侧边栏在右侧 */
  inset-inline-start: 0;        /* 替代 left: 0 */
  
  border-inline-end: 1px solid var(--border-color);  /* 替代 border-right */
}

/* 代码补全弹出框 */
.completion-popup {
  /* 弹出位置自动适配 */
  position: fixed;
  inset-inline-start: auto;     /* 让浏览器根据 dir 决定 */
  inset-inline-end: 0;
}

/* 特殊处理:代码始终 LTR */
.code-block,
pre,
code,
.monaco-editor {
  direction: ltr;               /* 代码始终保持从左到右 */
  text-align: left;
  unicode-bidi: isolate;        /* 隔离双向文本影响 */
}
// ===== src/components/RTLSwitch.tsx =====
// RTL 语言自动切换组件

import { watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import { rtlLocales } from '../i18n/config'

const { locale } = useI18n()

// 监听语言变化,自动设置 document.dir
watchEffect(() => {
  const isRTL = rtlLocales.includes(locale.value)
  document.documentElement.dir = isRTL ? 'rtl' : 'ltr'
  document.documentElement.lang = locale.value
  
  // 动态加载 RTL 样式
  if (isRTL) {
    document.body.classList.add('rtl-mode')
  } else {
    document.body.classList.remove('rtl-mode')
  }
  
  console.log(`[i18n] Locale changed to ${locale.value}, RTL: ${isRTL}`)
})

三、AI 交互层的多语言策略

3.1 用户语言自动检测

# ===== monkeycode/core/lang_detector.py =====
"""
MonkeyCode 多语言检测模块
基于以下信号综合判断用户的语言偏好:
1. 界面语言设置
2. 输入内容的语言特征
3. 代码注释语言
4. 项目文件中的语言线索
"""

import re
from dataclasses import dataclass
from typing import Optional
from collections import Counter

@dataclass
class LanguageDetectionResult:
    """语言检测结果"""
    primary_language: str           # 主语言代码,如 zh, en, ja
    confidence: float               # 置信度 0-1
    signals: dict                   # 各信号的贡献
    suggested_comment_style: str    # 建议的注释风格


class LanguageDetector:
    """多语言检测器"""
    
    # 各语言的典型字符特征
    LANGUAGE_PATTERNS = {
        'zh': re.compile(r'[\u4e00-\u9fff\u3400-\u4dbf]'),      # 汉字
        'ja': re.compile(r'[\u3040-\u309f\u30a0-\u30ff]'),      # 平假名/片假名
        'ko': re.compile(r'[\uac00-\ud7af\u1100-\u11ff]'),      # 韩文
        'ar': re.compile(r'[\u0600-\u06ff]'),                    # 阿拉伯文
        'ru': re.compile(r'[а-яА-ЯёЁ]'),                         # 西里尔字母
        'de': None,  # 使用字典方法
        'fr': None,
        'es': None,
    }
    
    # 常见关键词(用于辅助判断)
    KEYWORD_HINTS = {
        'zh': ['函数', '变量', '类', '导入', '定义', '返回', '打印', '如果', '否则'],
        'ja': ['関数', '変数', 'クラス', 'インポート', '定義', '返す', '出力'],
        'ko': ['함수', '변수', '클래스', '가져오기', '정의', '반환', '출력'],
        'de': ['Funktion', 'Variable', 'Klasse', 'Importieren', 'Definition'],
        'fr': ['fonction', 'variable', 'classe', 'importer', 'définition'],
        'es': ['función', 'variable', 'clase', 'importar', 'definición'],
    }
    
    def detect_from_code_context(
        self, 
        code: str, 
        comments: list[str],
        filename: Optional[str] = None
    ) -> LanguageDetectionResult:
        """
        从代码上下文中检测用户偏好的语言
        
        Args:
            code: 源代码文本
            comments: 提取出的注释列表
            filename: 文件名(可选)
            
        Returns:
            LanguageDetectionResult 包含检测结果和建议
        """
        signals = {}
        scores = Counter()
        
        # 信号1:注释语言分析
        comment_text = ' '.join(comments)
        if comment_text:
            comment_scores = self._analyze_text(comment_text)
            for lang, score in comment_scores.items():
                scores[lang] += score * 0.5  # 注释权重 0.5
            signals['comments'] = max(comment_scores.items(), key=lambda x: x[1])
        
        # 信号2:字符串字面量语言
        string_literals = self._extract_strings(code)
        if string_literals:
            string_scores = self._analyze_text(' '.join(string_literals))
            for lang, score in string_scores.items():
                scores[lang] += score * 0.3  # 字符串权重 0.3
            signals['strings'] = max(string_scores.items(), key=lambda x: x[1])
        
        # 信号3:变量命名风格(启发式)
        naming_hint = self._detect_naming_style(code)
        if naming_hint:
            scores[naming_hint] += 0.1
            signals['naming'] = naming_hint
        
        # 信号4:文件名和路径
        if filename:
            path_hint = self._detect_from_path(filename)
            if path_hint:
                scores[path_hint] += 0.1
                signals['path'] = path_hint
        
        # 计算最终结果
        if not scores:
            return LanguageDetectionResult(
                primary_language='en',
                confidence=0.3,
                signals={'fallback': 'no_signals'},
                suggested_comment_style='english'
            )
        
        primary_lang, primary_score = scores.most_common(1)[0]
        total_score = sum(scores.values())
        confidence = primary_score / total_score if total_score > 0 else 0
        
        # 映射到建议的注释风格
        style_map = {
            'zh': 'chinese',
            'ja': 'japanese',
            'ko': 'korean',
            'de': 'german',
            'fr': 'french',
            'es': 'spanish',
            'ru': 'russian',
        }
        
        return LanguageDetectionResult(
            primary_language=primary_lang,
            confidence=round(confidence, 2),
            signals=dict(signals),
            suggested_comment_style=style_map.get(primary_lang, 'english')
        )
    
    def _analyze_text(self, text: str) -> dict[str, float]:
        """分析文本中各语言字符的占比"""
        result = {}
        total_chars = len(text)
        if total_chars == 0:
            return result
            
        for lang, pattern in self.LANGUAGE_PATTERNS.items():
            if pattern:
                matches = pattern.findall(text)
                if matches:
                    result[lang] = len(matches) / total_chars
        
        # 对于拉丁语系语言,使用关键词匹配
        text_lower = text.lower()
        for lang, keywords in self.KEYWORD_HINTS.items():
            if lang not in self.LANGUAGE_PATTERNS or self.LANGUAGE_PATTERNS[lang] is None:
                count = sum(1 for kw in keywords if kw in text_lower)
                if count > 0:
                    result[lang] = count / len(keywords) * 0.3  # 归一化
        
        return result
    
    def _extract_strings(self, code: str) -> list[str]:
        """提取代码中的字符串字面量"""
        patterns = [
            r'"([^"]*)"',           # 双引号字符串
            r"'([^']*)'",           # 单引号字符串
            r'"""([\s\S]*?)"""',    # 三引号字符串
            r'f["\']([^"\']*?)["\']', # f-string 内容
        ]
        strings = []
        for pattern in patterns:
            strings.extend(re.findall(pattern, code))
        return [s for s in strings if len(s) > 1]  # 过滤短字符串
    
    def _detect_naming_style(self, code: str) -> Optional[str]:
        """通过命名风格推测语言偏好"""
        # 检测是否有中文拼音命名的变量
        pinyin_pattern = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*_(?:shiyong|mingcheng|neirong)')
        if pinyin_pattern.search(code):
            return 'zh'
        return None
    
    def _detect_from_path(self, filepath: str) -> Optional[str]:
        """从文件路径中检测语言线索"""
        path_lower = filepath.lower()
        hints = {
            'zh': ['README.zh', '说明', '文档', '指南', '教程'],
            'ja': ['README.ja', '説明', 'ガイド'],
            'ko': ['README.ko', '설명서', '가이드'],
        }
        for lang, keywords in hints.items():
            if any(kw in path_lower for kw in keywords):
                return lang
        return None

3.2 多语言 Prompt 增强

// ===== src/llm/multilingual-prompt.ts =====
/**
 * MonkeyCode 多语言 Prompt 构建器
 * 根据检测到的用户语言,动态调整发送给 LLM 的 prompt
 */

interface MultilingualPromptOptions {
  userLanguage: string           // 用户语言代码
  targetCommentStyle: string     // 目标注释风格
  codeLanguage: string           // 编程语言
  taskType: 'generate' | 'complete' | 'explain' | 'refactor' | 'debug'
  context?: string               // 额外上下文
}

// 语言特定的系统指令模板
const LANGUAGE_SYSTEM_PROMPTS: Record<string, string> = {
  'zh': `你是一个专业的 AI 编程助手。请遵循以下规则:
1. 生成的代码注释使用中文
2. 变量和函数命名使用英文(符合通用编码规范)
3. 错误信息和解释使用中文
4. 代码示例中的日志消息使用中文
5. 技术术语首次出现时附上英文原文`,

  'ja': `あなたはプロフェッショナルなAIプログラミングアシスタントです。以下のルールに従ってください:
1. コードのコメントは日本語で記述してください
2. 変数・関数名は英語を使用してください
3. エラーメッセージと解説は日本語で記述してください
4. コード例のログメッセージは日本語で記述してください`,

  'ko': `당신은 전문 AI 프로그래밍 어시스턴트입니다. 다음 규칙을 따르세요:
1. 코드 주석은 한국어로 작성하세요
2. 변수 및 함수 이름은 영어를 사용하세요
3. 오류 메시지와 설명은 한국어로 작성하세요
4. 코드 예제의 로그 메시지는 한국어로 작성하세요`,

  'en': `You are a professional AI programming assistant. Follow these rules:
1. Write code comments in English
2. Use English for variable and function names
3. Error messages and explanations should be in English
4. Log messages in code examples should be in English`,
  
  'de': `Du bist ein professioneller KI-Programmierassistent. Befolge diese Regeln:
1. Schreibe Code-Kommentare auf Deutsch
2. Verwende Englisch für Variablen- und Funktionsnamen
3. Fehlermeldungen und Erklärungen sollen auf Deutsch sein`,
}

export class MultilingualPromptBuilder {
  /**
   * 构建多语言感知的系统提示
   */
  buildSystemPrompt(options: MultilingualPromptOptions): string {
    const basePrompt = LANGUAGE_SYSTEM_PROMPTS[options.userLanguage] 
      || LANGUAGE_SYSTEM_PROMPTS['en']
    
    // 添加编程语言特定指令
    const languageHints = this.getLanguageSpecificHints(options.codeLanguage)
    
    // 添加任务类型特定指令
    const taskHints = this.getTaskSpecificHints(options.taskType)
    
    return [
      basePrompt,
      languageHints,
      taskHints,
      options.context || '',
      `\n\n当前用户界面语言: ${options.userLanguage}`,
      `\n目标编程语言: ${options.codeLanguage}`,
    ].filter(Boolean).join('\n\n')
  }
  
  /**
   * 构建用户请求的多语言版本
   */
  buildUserRequest(
    originalRequest: string, 
    detectedLanguage: string
  ): string {
    // 如果用户用自己的语言提问,保持原样
    // 但可以添加语言标记帮助 LLM 更好理解
    return `[用户语言: ${detectedLanguage}]\n${originalRequest}`
  }
  
  private getLanguageSpecificHints(codeLang: string): string {
    const hints: Record<string, string> = {
      python: `
Python 特定规范:
- 遵循 PEP 8 编码规范
- 使用 type hints(类型注解)
- docstring 使用 Google 风格或 NumPy 风格`,
      
      typescript: `
TypeScript 特定规范:
- 优先使用 strict 模式
- 接口命名使用 PascalCase(如 IUserService)
- 使用 enum 而非联合字符串常量`,
      
      go: `
Go 特定规范:
- 遵循 Effective Go 和官方 Style Guide
- 错误处理使用显式 error 返回
- 接口命名以 er 结尾(如 Reader, Writer)`,
    }
    return hints[codeLang.toLowerCase()] || ''
  }
  
  private getTaskSpecificHints(taskType: string): string {
    const hints: Record<string, string> = {
      generate: `代码生成任务:
- 生成完整、可运行的代码
- 包含必要的错误处理
- 添加适当的注释和文档`,
      
      explain: `代码解释任务:
- 用清晰易懂的方式解释代码逻辑
- 指出关键的设计决策
- 如有改进空间,请提出建议`,
      
      debug: `调试任务:
- 分析可能的错误原因
- 提供修复方案
- 解释为什么会出现这个错误`,
    }
    return hints[taskType] || ''
  }
}

四、翻译工作流与社区协作

4.1 翻译流程

┌─────────────────────────────────────────────────────────────────┐
│                  MonkeyCode 翻译工作流                            │
│                                                                 │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐  │
│  │  源文件   │ => │  上传至   │ => │  社区翻译  │ => │  自动同步  │  │
│  │ (中文)   │    │  Crowdin │    │  (志愿者) │    │  到仓库   │  │
│  └──────────┘    └──────────┘    └──────────┘    └──────────┘  │
│                                                                 │
│  详细步骤:                                                      │
│  1. 开发者在 src/i18n/locales/zh-CN.json 更新源文案             │
│  2. CI 自动触发上传到 Crowdin 翻译平台                           │
│  3. 翻译者收到通知,在 Crowdin 网页端进行翻译                     │
│  4. 其他翻译者/审核者进行投票和审核                              │
│  5. 达到阈值后自动合并到主分支                                   │
│  6. 每次发布时包含所有已翻译的语言包                             │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.2 翻译文件结构

{
  "_meta": {
    "version": "4.2.1",
    "lastUpdated": "2026-06-30",
    "totalKeys": 342,
    "translatedKeys": 338,
    "completionRate": "98.8%",
    "translators": ["Alice", "田中太郎", "김철수", "Hans"]
  },
  "app": {
    "title": "MonkeyCode",
    "subtitle": "开源 AI 编程助手",
    "tagline": "让编程更智能、更高效",
    "description": "MonkeyCode 是一款完全开源的 AI 编程助手,支持私有化部署和多语言"
  },
  "nav": {
    "home": "首页",
    "editor": "编辑器",
    "settings": "设置",
    "extensions": "插件市场",
    "community": "社区"
  },
  "editor": {
    "placeholder": "开始输入代码或描述你的需求...",
    "complete": "补全",
    "generate": "生成",
    "explain": "解释",
    "refactor": "重构",
    "debug": "调试",
    "test": "生成测试",
    "comment": "添加注释",
    "docstring": "生成文档字符串",
    "chat": "AI 对话",
    "actions": {
      "accept": "接受 (Tab)",
      "dismiss": "关闭 (Esc)",
      "next": "下一个 (↓)",
      "prev": "上一个 (↑)"
    }
  },
  "settings": {
    "general": "常规设置",
    "appearance": "外观",
    "editor": "编辑器",
    "ai": "AI 模型",
    "advanced": "高级选项",
    "language": {
      "label": "界面语言",
      "description": "选择 MonkeyCode 的显示语言",
      "auto_detect": "自动检测"
    },
    "theme": {
      "label": "主题",
      "light": "浅色",
      "dark": "深色",
      "system": "跟随系统"
    }
  },
  "ai": {
    "thinking": "正在思考...",
    "generating": "正在生成...",
    "complete": "完成!",
    "error": "出错了,请重试",
    "rate_limit": "请求过于频繁,请稍后再试",
    "context_too_long": "上下文过长,请拆分任务",
    "suggestions": {
      "code_completion": "代码补全",
      "function_generation": "生成函数",
      "test_case": "生成测试用例",
      "bug_fix": "修复建议",
      "optimization": "性能优化建议"
    }
  },
  "common": {
    "save": "保存",
    "cancel": "取消",
    "confirm": "确认",
    "delete": "删除",
    "edit": "编辑",
    "copy": "复制",
    "paste": "粘贴",
    "search": "搜索",
    "loading": "加载中...",
    "no_results": "无结果",
    "retry": "重试",
    "back": "返回",
    "next": "下一步",
    "previous": "上一步",
    "close": "关闭",
    "learn_more": "了解更多",
    "view_docs": "查看文档",
    "report_issue": "反馈问题",
    "contribute": "参与贡献"
  },
  "footer": {
    "opensource": "开源项目",
    "license": "Apache License 2.0",
    "github": "GitHub",
    "community": "社区讨论",
    "twitter": "Twitter/X",
    "discord": "Discord"
  }
}

五、实战案例:为 MonkeyCode 添加新语言支持

5.1 步骤一:创建语言包

# 1. 创建新的语言文件
mkdir -p src/i18n/locales
cp src/i18n/locales/en-US.json src/i18n/locales/vi-VN.json  # 以英语为基础

# 2. 注册语言
# 编辑 src/i18n/index.ts,在 availableLocales 中添加:
# { code: 'vi-VN', name: 'Tiếng Việt', nativeName: 'Tiếng Việt', rtl: false }

# 3. 导入语言包
import viVN from './locales/vi-VN.json'

# 4. 在 i18n 实例中注册
messages: {
  // ...existing locales
  'vi-VN': viVN,
}

5.2 步骤二:翻译核心词条

{
  "app": {
    "title": "MonkeyCode",
    "subtitle": "Trợ lý lập trình AI mã nguồn mở",
    "tagline": "Làm cho lập trình thông minh và hiệu quả hơn"
  },
  "editor": {
    "placeholder": "Bắt đầu nhập mã hoặc mô tả nhu cầu của bạn...",
    "complete": "Hoàn thành",
    "generate": "Tạo ra",
    "explain": "Giải thích",
    "refactor": "Tái cấu trúc",
    "debug": "Gỡ lỗi"
  },
  "common": {
    "save": "Lưu",
    "cancel": "Hủy",
    "confirm": "Xác nhận",
    "delete": "Xóa",
    "edit": "Chỉnh sửa"
  }
}

5.3 步骤三:提交 PR

# 创建特性分支
git checkout -b feat/i18n-vietnamese

# 添加翻译文件
git add src/i18n/locales/vi-VN.json src/i18n/index.ts

# 提交更改
git commit -m "feat(i18n): add Vietnamese (vi-VN) language support"

# 推送并创建 PR
git push origin feat/i18n-vietnamese
gh pr create --title "feat(i18n): 添加越南语支持" \
  --body "## 变更内容
- 新增越南语 (vi-VN) 语言包
- 翻译了 340+ 个核心词条
- 已通过本地验证测试

## 测试清单
- [x] 语言切换正常
- [x] UI 显示正确
- [x] RTL 不受影响
- [x] 无遗漏的未翻译文本

🙏 请 @i18n-team 审核翻译质量"

六、国际化最佳实践总结

6.1 DO & DON'T

## ✅ 推荐做法

1. **始终使用 i18n 函数包装文本**
   ```vue
   <!-- ✅ 正确 -->
   <h1>{{ $t('app.title') }}</h1>
   
   <!-- ❌ 错误 -->
   <h1>MonkeyCode</h1>
  1. 插值使用参数而非拼接

    // ✅ 正确
    $t('welcome.user', { name: userName })
    
    // ❌ 错误
    `${$t('welcome.prefix')}${userName}`
    
  2. 日期/数字使用 API 格式化

    // ✅ 正确
    d(date, 'short')         // 2026/6/30 或 6/30/2026
    n(price, 'currency')     // ¥100 或 $100
    
    // ❌ 错误
    date.toLocaleDateString()  // 格式不可控
    
  3. 图标 + 文本组合注意语序

    <!-- ✅ 正确:图标和文本整体翻转 -->
    <button>
      <IconSave />
      <span>{{ $t('common.save') }}</span>
    </button>
    
    <!-- 注意:某些语言可能期望 图标在前 或 图标在后 -->
    

❌ 避免做法

  1. 硬编码文本
  2. 在翻译字符串中嵌入 HTML
  3. 假设句子结构在各语言中相同
  4. 忽略复数形式差异
  5. 忘记测试 RTL 布局

### 6.2 性能优化技巧

| 优化策略 | 说明 | 效果 |
|---------|------|------|
| **按需加载语言包** | 只加载当前使用的语言 | 首次加载减少 60%+ |
| **懒加载罕见语言** | 首次切换时再下载 | 初始包体积更小 |
| **翻译缓存** | localStorage 缓存已加载语言包 | 切换瞬间完成 |
| **CDN 分发** | 语言包通过 CDN 加载 | 全球访问加速 |
| **Tree Shaking** | 未使用的翻译 key 不打包 | 包体积最小化 |

---

## 七、参与 MonkeyCode 国际化

MonkeyCode 的国际化离不开全球社区的贡献!以下是你可以参与的方式:

### 7.1 如何贡献翻译

1. **Fork 仓库**: `git clone https://github.com/monkeycode-ai/monkeycode.git`
2. **选择语言**: 查看 `src/i18n/locales/` 中哪些语言需要完善
3. **进行翻译**: 编辑对应的 JSON 文件
4. **本地测试**: 切换到该语言验证显示效果
5. **提交 PR**: 附上截图和测试结果

### 7.2 当前需要帮助的语言

| 语言 | 完成度 | 急需程度 | 备注 |
|------|-------|---------|------|
| 阿拉伯语 (ar-SA) | 45% | 🔴 高 | RTL 适配需额外关注 |
| 泰语 (th-TH) | 60% | 🟠 中 | |
| 印尼语 (id-ID) | 55% | 🟠 中 | |
| 波兰语 (pl-PL) | 70% | 🟡 低 | |
| 土耳其语 (tr-TR) | 65% | 🟡 低 | |

### 7.3 Issue 反馈

如果你在使用中发现任何国际化问题,欢迎通过 GitHub Issue 反馈:

📮 **Issue 地址**: [https://github.com/monkeycode-ai/monkeycode/issues](https://github.com/monkeycode-ai/monkeycode/issues)

**请使用以下标签**:
- `i18n`: 翻译/语言相关
- `bug`: 显示错误
- `feature`: 新语言需求
- `rtl`: 从右到左布局问题

---

## 结语

**"让每一位开发者都用母语享受 AI 编程的乐趣"** — 这是 MonkeyCode 国际化团队的愿景。

从 12 种语言的 UI 支持,到智能的多语言代码生成;从完善的翻译工作流,到开放的社区贡献机制——MonkeyCode 正在努力让 AI 编程助手真正服务于全球开发者。

开源的力量在于协作,国际化的价值在于包容。欢迎你加入 MonkeyCode 的国际化建设,让更多人用自己熟悉的语言,体验最前沿的 AI 编程技术!

---

> 💡 **快速开始使用 MonkeyCode**:
> - 📦 安装: `pip install monkeycode` 或访问 [GitHub Releases](https://github.com/monkeycode-ai/monkeycode/releases)
> - 🐛 发现问题? [提交 Issue](https://github.com/monkeycode-ai/monkeycode/issues)
> - 💬 加入讨论: [GitHub Discussions](https://github.com/monkeycode-ai/monkeycode/discussions)
> - 🌍 贡献翻译: 查看 [CONTRIBUTING.md](https://github.com/monkeycode-ai/monkeycode/blob/main/CONTRIBUTING.md)

**MonkeyCode — 开源的 AI 编程助手,属于每一位开发者。** 🚀
posted on 2026-06-30 11:32  MonkeyCode  阅读(16)  评论(0)    收藏  举报