frappe-core-translation について
Frappe アプリをバージョン14、15、16で翻訳する開発者向けのリファレンススキルです。翻訳 API、文字列抽出、翻訳ファイル形式、右から左へ書く言語への対応を説明します。
主な機能
- 01PythonとJavaScriptの翻訳API
- 02ファイル形式ごとの文字列抽出ルール
- 03CSVとPO/MOの翻訳ワークフロー
- 04翻訳作業用のBenchコマンド
- 05右から左へ書く言語への対応
活用シーン
- 01カスタムアプリに翻訳可能な文字列を追加
- 02未翻訳テキストの抽出と取り込み
- 03CSV翻訳を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+] | N/A |
| 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 トークナイザー [v15+] / 正規表現 [v14] | __("...") の呼び出し |
.html | 正規表現 | Jinja 内の {{ _("...") }} |
.vue | JS と同じ | スクリプト/テンプレート内の __("...") |
.json | DocType パーサー | ラベル、説明、オプション |
重要:抽出ツールは 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 なし)
- 必ずすべてのフィールドを二重引用符で囲んでください
- コンテキスト列は省略可能ですが、必ず存在させてください(使用しない場合は空文字列)
- 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-leftではなくmargin-inline-start)を必ず使用してください - 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 対応