关于 frappe-core-translation
面向开发者的 Frappe 应用翻译参考技能,涵盖 14、15 和 16 版。内容包括翻译 API、字符串提取、翻译文件格式及从右向左语言支持。
主要功能
- 01Python 和 JavaScript 翻译 API
- 02按文件类型划分的字符串提取规则
- 03CSV 与 PO/MO 翻译流程
- 04用于翻译任务的 Bench 命令
- 05从右向左语言支持
适用场景
- 01为自定义应用添加可翻译字符串
- 02提取并导入未翻译文本
- 03将 CSV 翻译迁移到 PO 文件
- 04适配从右向左书写的语言界面
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ impertio-studio/ frappe_claude_skill_package --skill frappe-core-translation安装后在 Claude Code 中输入/frappe-core-translation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/anti-patterns.mdapi-reference.mdcsv-and-bench.md详细介绍
Frappe 翻译 / i18n
适用于 v14、v15 和 v16 的 Frappe 应用翻译确定性模式。
快速参考
| 任务 | Python | JavaScript |
|---|---|---|
| 翻译字符串 | _("Hello") | __("Hello") |
| 带替换参数 | _("Hello {0}").format(name) | __("Hello {0}", [name]) |
| 带上下文 | _("Change", context="Coins") | __("Change", null, "Coins") |
| 延迟翻译(模块级) | _lt("Pending") [v15+] | 不适用 |
| 检查是否为 RTL | frappe.utils.is_rtl() | frappe.utils.is_rtl() |
决策树
Need to translate a string?
├── In Python (.py)?
│ ├── Inside a function/method → _("text {0}").format(val)
│ ├── Module-level constant [v15+] → _lt("text")
│ └── Module-level constant [v14] → define inside function or use lazy
├── In JavaScript (.js)?
│ └── ALWAYS → __("text {0}", [val])
├── In Jinja template (.html)?
│ └── {{ _("text") }}
├── In Vue (.vue)?
│ └── __("text") in <script>, {{ __("text") }} in <template>
└── DocType label/description/option?
└── Auto-extracted — no _() needed
Where do translations live?
├── v14 → apps/{app}/{app}/translations/{lang}.csv
├── v15+ → apps/{app}/{app}/locale/{lang}/LC_MESSAGES/{app}.po
└── User overrides → Translation DocType (highest priority)
Need to extract untranslated strings?
├── v14 → bench --site {site} get-untranslated {lang} {output}
└── v15+ → bench generate-pot-file --app {app}
翻译优先级(从高到低)
| 优先级 | 来源 | 范围 |
|---|---|---|
| 1 | Translation DocType(用户覆盖) | 每个站点 |
| 2 | MO 文件(locale/{lang}/.../{app}.mo) | 每个应用 [v15+] |
| 3 | CSV 文件(translations/{lang}.csv) | 每个应用 |
| 4 | 父语言(例如,pt-BR 对应的 pt) | 回退 |
版本差异
| 功能 | v14 | v15 | v16 |
|---|---|---|---|
_() / __() | 是 | 是 | 是 |
_lt() 延迟翻译 | 否 | 是 | 是 |
| CSV 翻译 | 是 | 是(旧版) | 是(旧版) |
| PO/MO(gettext) | 否 | 是 | 是 |
bench generate-pot-file | 否 | 是 | 是 |
| Babel JS 提取器 | 否 | 是 | 是 |
_() 的类型提示 | 否 | 否 | 是 |
自动提取的字符串(无需使用 _())
这些内容由框架自动提取:
- DocType 标签和说明
- Select 字段选项(每行一个选项)
- 工作流状态和操作
- Print Format 标签
- 报告列标签
- 通知主题(不包括正文)
- 仪表板图表标签
字符串提取规则
| 文件类型 | 提取器 | 提取内容 |
|---|---|---|
.py | Babel(AST) | _("...")、_lt("...") 调用 |
.js | Babel tokenizer [v15+] / regex [v14] | __("...") 调用 |
.html | Regex | Jinja 中的 {{ _("...") }} |
.vue | 与 JS 相同 | script/template 中的 __("...") |
.json | DocType parser | 标签、说明、选项 |
重要:提取器基于 AST/令牌工作,无法提取动态构造的字符串。请参阅反模式。
反模式(绝不要这样做)
| 模式 | 为什么会出错 | 正确写法 |
|---|---|---|
_(f"Hello {name}") | 无法提取 f-string | _("Hello {0}").format(name) |
_("Hello " + name) | 拼接会拆分字符串 | _("Hello {0}").format(name) |
_("Welcome %s") % name | 无法提取旧式格式 | _("Welcome {0}").format(name) |
__(`Hello ${name}`) | 无法提取模板字面量 | __("Hello {0}", [name]) |
_(" Hello ") | 首尾空格会被移除 | _("Hello") |
_("item" if x else "items") | _() 中使用了三元表达式 | _("item") if x else _("items") |
_(variable) | 无法提取变量 | _("Known String") |
完整的反模式目录及代码示例:references/anti-patterns.md
CSV 翻译文件格式
位置:apps/{app}/{app}/translations/{lang}.csv
"source","translation","context"
"Hello","Hallo",""
"Change","Wisselgeld","Coins"
"Change","Wijziging","Amendment"
- 始终使用 UTF-8 编码(不带 BOM)
- 始终使用双引号括起所有字段
- Context 列为可选,但必须存在(未使用时填写空字符串)
- 无需注册 hooks——系统会自动从
translations/目录发现文件
PO/MO 文件 [v15+]
位置:apps/{app}/{app}/locale/{lang}/LC_MESSAGES/{app}.po
# Generate POT template
bench generate-pot-file --app {app}
# Migrate existing CSV to PO
bench migrate-csv-to-po --app {app}
# Compile PO to MO (required for runtime)
bench compile-po-to-mo --app {app}
PO 文件遵循标准 GNU gettext 格式。可使用任意 PO 编辑器(Poedit、Weblate、Transifex)。
Bench 命令
| 命令 | 版本 | 用途 |
|---|---|---|
bench --site {site} get-untranslated {lang} {output.csv} | 全部 | 导出未翻译的字符串 |
bench update-translations {lang} {untranslated.csv} {translated.csv} | 全部 | 导入翻译 |
bench generate-pot-file --app {app} | v15+ | 生成 .pot 模板 |
bench migrate-csv-to-po --app {app} | v15+ | 将 CSV 转换为 PO 格式 |
bench compile-po-to-mo --app {app} | v15+ | 将 PO 编译为二进制 MO |
RTL 支持
硬编码的 RTL 语言:ar(阿拉伯语)、he(希伯来语)、fa(波斯语/法尔西语)、ps(普什图语)
# Python
if frappe.utils.is_rtl():
# Apply RTL-specific logic
// JavaScript
if (frappe.utils.is_rtl()) {
// Apply RTL-specific logic
}
- Frappe 会自动为
<html>元素应用dir="rtl" - 为确保兼容 RTL,始终使用逻辑 CSS 属性(
margin-inline-start,而非margin-left) - 启用 RTL 语言时,会自动加载 Bootstrap RTL 样式表
自定义应用翻译工作流
为自定义应用添加翻译:
- 使用
_()/__()和位置占位符编写可翻译字符串 - 提取未翻译的字符串:
- v14:
bench --site {site} get-untranslated {lang} untranslated.csv - v15+:
bench generate-pot-file --app {app}
- v14:
- 翻译提取出的字符串(手动翻译或使用 PO 编辑器)
- 放置翻译文件:
- CSV:
apps/{app}/{app}/translations/{lang}.csv - PO:
apps/{app}/{app}/locale/{lang}/LC_MESSAGES/{app}.po
- CSV:
- 编译(仅适用于 v15+ PO):
bench compile-po-to-mo --app {app} - 清除缓存:
bench --site {site} clear-cache
参考文件
| 文件 | 内容 |
|---|---|
| references/api-reference.md | 完整的 Python _() 和 JS __() API,包含所有签名和边缘情况 |
| references/csv-and-bench.md | CSV 格式规范、bench 命令、PO/MO 工作流、自定义应用设置 |
| references/anti-patterns.md | 完整的反模式目录,包含失败示例和修正示例 |
评论
支持 Markdown