国际化
N.E.K.O. 支持 5 种语言,并提供客户端语言切换功能。
支持的语言
| 代码 | 语言 | 文件 |
|---|---|---|
en | English | static/locales/en.json |
zh-CN | 简体中文 | static/locales/zh-CN.json |
zh-TW | 繁体中文 | static/locales/zh-TW.json |
ja | 日语 | static/locales/ja.json |
ko | 韩语 | static/locales/ko.json |
工作原理
- 页面加载时,系统检测用户的语言:
- 首先检查 Steam 客户端语言(如果可通过
/api/config/steam_language获取) - 回退到浏览器语言偏好设置
- 尊重用户手动设置(
/api/config/user_language)
- 首先检查 Steam 客户端语言(如果可通过
- 加载对应的语言 JSON 文件
- 使用 data 属性或直接 JS 替换方式替换 DOM 中的文本内容
语言文件格式
语言文件是使用点号分隔键名的扁平 JSON 对象:
json
{
"nav.home": "Home",
"nav.settings": "Settings",
"chat.placeholder": "Type a message...",
"chat.send": "Send"
}国际化标记模式
HTML:data-i18n 属性
html
<!-- Element text -->
<span data-i18n="chat.send">发送</span>
<button data-i18n="common.ok">确定</button>
<!-- Placeholder -->
<input placeholder="请输入" data-i18n-placeholder="chat.inputPlaceholder">
<!-- Title attribute -->
<button title="关闭" data-i18n-title="common.close">X</button>
<!-- Alt attribute -->
<img alt="对话" src="chat.png" data-i18n-alt="chat.title">JavaScript:带回退的 window.t()
始终提供中文回退以实现优雅降级:
javascript
// Display text
showStatusToast(window.t ? window.t('common.connectionSuccess') : '连接成功', 2000);
// Error messages
showMessage(window.t ? window.t('common.saveFailed') : '保存失败', 'error');
// With parameters
showMessage(window.t ? window.t('files.deleted', { count }) : `删除了 ${count} 个文件`);不需要国际化的内容
javascript
// ✅ Skip: console debug messages
console.log('连接成功');
// ✅ Skip: internal logic detection
if (status.includes('已离开')) { ... }
// ✅ Skip: data keys (character field names)
const name = characterData['档案名'];
// ✅ Skip: already wrapped
showMessage(window.t ? window.t('key') : 'fallback');模块与文件映射
检查未翻译字符串时,请参考以下模块分组:
| 模块 | HTML 文件 | JS 文件 |
|---|---|---|
main | index.html | app.js |
live2d | live2d*.html | live2d*.js |
voice | voice*.html | voice*.js, tts*.js |
steam | steam*.html | steam*.js |
settings | settings*.html, config*.html | settings*.js, config*.js |
chat | memory_browser.html, chara_manager.html | memory_browser.js, chara_manager.js |
HTML + 图标冲突
当 i18next 通过 textContent 更新文本时,会销毁元素内部的 <img> 标签。如果你的翻译内容包含 HTML 图标,请将完整的 HTML 写入语言 JSON 文件中,这样系统会改用 innerHTML。参见开发者笔记。
添加新语言
- 在
static/locales/中创建新文件(例如fr.json) - 复制
en.json的结构并翻译所有值 - 在前端语言选择器中添加该语言选项
- 更新
utils/language_utils.py以识别新的语言代码
后端翻译
后端也通过 TranslationService(utils/translation_service.py)支持翻译:
- 首选:
googletrans库 - 回退:
translatepy库 - 最终回退:基于 LLM 的翻译
当用户语言与角色语言不同时,会话管理器中的 translate_if_needed() 会使用此功能。
