odoo-i18n について
odoo-i18nは、Odoo 14~19の翻訳とローカライズを扱う開発者向けスキルです。文字列の抽出、.poファイルの検証と不足レポート、Odoo CLIによる翻訳のインポートやエクスポートを支援します。
主な機能
- 01翻訳対象文字列の抽出
- 02.poの構文と内容の検証
- 03翻訳不足のレポート
- 04.poファイルのマージと変換
- 05Odoo CLIでのインポートとエクスポート
- 06言語別ルールの確認
活用シーン
- 01Odooモジュールの翻訳ファイル生成
- 02リリース前の.poファイル検証
- 03翻訳カバレッジ不足の把握
- 04Odooデータベースへの翻訳登録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ahmed-lakosha/ odoo-plugins --skill odoo-i18nインストール後、Claude Code で/odoo-i18nを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
scripts/__init__.py_common.pyi18n_converter.pyi18n_extractor.pyi18n_reporter.pyi18n_validator.py詳細
Odoo i18n スキル
Odoo 14~19 の国際化(i18n)とローカライゼーション(l10n)に関する深い専門知識を提供します。
重要な翻訳ルール
- 絶対に
_()内で f-string を使わないでください。%形式を使用します:_('Record %s') % name - 絶対に
_()内で文字列を連結しないでください。翻訳者に文全体を渡します。 - クラスレベルの文字列(選択値、クラス属性)には
_lt()を使用します - 絶対に
string=フィールド属性を_()で囲まないでください。Odoo が自動的に翻訳します。 .poファイルは BOM なしの UTF-8 として保存します。- アラビア語の
.poファイルでは、Plural-Forms ヘッダーにnplurals=6が必要です。 .poファイルを編集した後は、必ずモジュールを更新します:-u module --stop-after-init
ワークフロー 1:翻訳対象の文字列を抽出する
Odoo モジュールをスキャンし、翻訳対象の文字列をすべて抽出して、.pot(テンプレート)ファイルと .po(言語)ファイルを生成します。
使用方法
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_extractor.py --module <path> --lang <code> [--output <dir>] [--no-pot] [--verbose]
| 引数 | 必須 | 説明 |
|---|---|---|
--module | はい | Odoo モジュールディレクトリのパス |
--lang | はい | 対象言語コード(例:ar、fr、tr) |
--output | いいえ | カスタム出力ディレクトリ(デフォルト:module/i18n/) |
--no-pot | いいえ | .pot テンプレートの生成をスキップ |
--verbose | いいえ | 抽出した文字列をすべて表示 |
抽出対象
Python(*.py) -- _('...') および _lt('...'):
# Extracted:
raise UserError(_('Record %s not found') % name)
state = fields.Selection([('draft', _lt('Draft'))])
# NOT extracted: _(variable), _(f'Hello {name}')
XML(*.xml) -- string=、help=、placeholder= 属性、メニュー/アクションの name=、HTML テキスト:
<field name="state" string="Status"/>
<h1>Welcome to our website</h1>
<record id="view_my_form" model="ir.ui.view">
JavaScript(*.js) -- _t('...') および _lt('...'):
const msg = _t("Save Changes"); // extracted
const msg = _t(someVariable); // NOT extracted
生成されるファイル構成
# Translation template for my_module
msgid ""
msgstr ""
"Project-Id-Version: Odoo Module my_module\n"
"Content-Type: text/plain; charset=UTF-8\n"
#: models/my_model.py:45
#, python-format
msgid "Record %s not found"
msgstr ""
代替方法:Odoo 組み込みの抽出ツール
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-export --modules=my_module --language=ar \
--output=my_module/i18n/ar.po --stop-after-init
Odoo の CLI 抽出ツールは、プラグインの抽出ツールでは対象とならないデータベース内の文字列(モデル名、アクション名)も含めます。本番環境では、組み込みの抽出ツールのほうがより完全です。
抽出後の手順
.poファイルを翻訳エディター(Poedit、Virtaal、またはテキストエディター)で開きます- すべての
msgstrエントリーに翻訳を入力します - 検証します:
i18n_validator.py --po-file path/to/ar.poを実行します - 翻訳率を確認します:
i18n_reporter.py --module path/ --lang arを実行します - Odoo に読み込みます:モジュールを更新するか、エクスポート/インポートのワークフローを使用します
ワークフロー 2:.po ファイルを検証する
.po ファイルの構文エラー、エンコーディングの問題、空の翻訳、fuzzy エントリー、書式指定子の不一致、アラビア語/RTL 固有の問題を検証します。
使用方法
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_validator.py --po-file <path> [--lang <code>] [--strict] [--output <file>]
| 引数 | 必須 | 説明 |
|---|---|---|
--po-file | はい | 検証する .po ファイルのパス |
--lang | いいえ | 言語固有のチェックに使用する言語コード(ファイル名から自動検出) |
--strict | いいえ | 未翻訳の文字列を警告ではなくエラーとして扱う |
--output | いいえ | 標準出力ではなく、レポートをファイルに書き込む |
検証内容
構文: UTF-8 エンコーディング(BOM/Latin-1 なし)、Content-Type/charset/Language/MIME-Version を含むヘッダー、適切に引用符で囲まれた文字列、解析エラーがないこと。
翻訳: 空の msgstr(未翻訳)、確認が必要な fuzzy フラグ、重複する msgid、廃止済み(#~)エントリー。
書式指定子: %s/%d/%f の数が一致していること、名前付き書式指定子 %(name)s がすべて含まれていること:
# WRONG - missing second %s:
msgid "Invoice %s due on %s"
msgstr "fatura %s"
# CORRECT:
msgid "Invoice %s due on %s"
msgstr "fatura %s vadesi %s"
アラビア語固有(--lang ar): アラビア文字が含まれていること、Latin-1 によるエンコーディングのアーティファクト、方向制御文字、nplurals=6 が必須であること、BIDI 上書きの警告。
よくあるエラーと修正方法
「Charset must be UTF-8」:
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_converter.py --action convert --po ar.po --output ar_fixed.po
「Fuzzy translation (needs review)」 -- 確認後に fuzzy フラグを削除します:
# Before: # After:
#, fuzzy, python-format #, python-format
msgid "Record %s not found" msgid "Record %s not found"
msgstr "record not found" msgstr "record not found"
「Arabic should have nplurals=6」:
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
CI/CD との統合
- name: Validate Arabic translations
run: python odoo-i18n/scripts/i18n_validator.py --po-file my_module/i18n/ar.po --lang ar --strict
終了コード 0 = 成功(警告がある場合もあります)、1 = 失敗(エラーあり)。
ワークフロー 3:不足している翻訳を見つける
モジュールのソースファイルに含まれる翻訳対象の文字列と既存の .po ファイルを比較し、不足または未完了の翻訳を報告します。
使用方法
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_reporter.py --module <path> --lang <code> [--format text|json|csv] [--output <file>] [--min-pct <N>]
| 引数 | 必須 | 説明 |
|---|---|---|
--module | はい | Odoo モジュールディレクトリへのパス |
--lang | はい | チェックする言語コード(例:ar、fr) |
--format | いいえ | 出力形式:text(デフォルト)、json、csv |
--output | いいえ | 標準出力ではなく、レポートをファイルに書き込みます |
--min-pct | いいえ | 翻訳率がしきい値を下回ると終了コード 1 を返します |
レポートの見方
- Missing:ソースコードにはあるものの、
.poにエントリがない文字列です - Empty in .po:エントリはありますが、
msgstrが""(未翻訳)です - Fuzzy:自動照合されたため、人による確認が必要です。ユーザーには表示されません(Odoo はソースにフォールバックします)
- Completion % = 翻訳済み / 有効な文字列の合計 * 100(空でない、fuzzy でない、廃止されていない文字列)
ワークフロー:未翻訳箇所の修正
i18n_reporter.pyを実行して不足箇所を特定します- Poedit、Virtaal、またはテキストエディターで
.poを開きます - 不足している
msgstrエントリを入力します - 文字列が
.poにまったくない場合は、まずi18n_extractor.pyを実行します i18n_validator.pyで検証しますi18n_reporter.pyを再実行して網羅率を確認します
ソース変更後の .po の更新
# 1. Re-extract new strings
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_extractor.py --module /path/ --lang ar --no-pot
# 2. Merge (preserves existing translations)
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_converter.py \
--action merge --base /path/i18n/ar.po --new /path/i18n/ar.po --output /path/i18n/ar_merged.po
# 3. Check remaining gaps
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_reporter.py --module /path/ --lang ar
ワークフロー 4:Odoo CLI でのエクスポート/インポート
PostgreSQL と有効なデータベースが必要です。
翻訳のエクスポート
# Single module
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-export --modules=my_module --language=ar \
--output=my_module/i18n/ar.po --stop-after-init
# Export .pot template (no --language = empty msgstr)
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-export --modules=my_module \
--output=my_module/i18n/my_module.pot --stop-after-init
# Multiple modules / all installed
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-export --modules=mod1,mod2 --language=ar --output=combined_ar.po --stop-after-init
翻訳のインポート
# Import .po
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-import=my_module/i18n/ar.po --language=ar --modules=my_module --stop-after-init
# Import and overwrite existing
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-import=my_module/i18n/ar.po --language=ar \
--modules=my_module --i18n-overwrite --stop-after-init
# Multiple languages
for lang in ar fr tr; do
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-import=my_module/i18n/${lang}.po --language=${lang} \
--modules=my_module --stop-after-init
done
言語の読み込み
python odoo-bin -c conf/myproject.conf -d mydb --load-language=ar --stop-after-init
python odoo-bin -c conf/myproject.conf -d mydb --load-language=ar,fr,tr --stop-after-init
シェルで確認/有効化します:
# python odoo-bin shell -d mydb
langs = self.env['res.lang'].with_context(active_test=False).search([])
for lang in langs:
print(f"[{'ACTIVE' if lang.active else 'inactive'}] {lang.code}: {lang.name}")
# Activate
lang = self.env['res.lang'].with_context(active_test=False).search([('code', '=', 'ar')])
lang.active = True
self.env.cr.commit()
モジュールの更新(最も簡単な再読み込み)
python -m odoo -c conf/myproject.conf -d mydb -u my_module --stop-after-init
Odoo 17 以降の仕様
翻訳は内部的に JSON 用語として保存されますが、エクスポート形式は引き続き .po です。キャッシュをクリアします:
# python odoo-bin shell -d mydb
self.env['ir.translation'].clear_caches()
self.env.cr.commit()
Web サイトの翻訳
python odoo-bin -c conf/myproject.conf -d mydb \
--i18n-export --modules=website,my_theme_module --language=ar \
--output=website_ar.po --stop-after-init
翻訳ファイルの場所
module/i18n/
module.pot <- Template (not loaded by Odoo)
ar.po <- Arabic
ar_SA.po <- Saudi variant (overrides ar.po entries)
fr.po <- French
tr.po <- Turkish
ユーティリティ:.po ファイルの統合とクリーンアップ
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_converter.py --action merge --base ar.po --new ar_new.po --output ar_merged.po
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_converter.py --action clean --po ar.po
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_converter.py --action stats --po ar.po
python ${CLAUDE_PLUGIN_ROOT}/odoo-i18n/scripts/i18n_converter.py --action convert --po ar.po --output ar_fixed.po
対応言語のクイックリファレンス
| コード | 言語 | RTL? | 複数形 |
|---|---|---|---|
ar / ar_SA / ar_AE | アラビア語(バリエーション) | はい | 6 |
en / en_US | 英語 | いいえ | 2 |
fr / fr_FR | フランス語 | いいえ | 2 |
tr | トルコ語 | いいえ | 2 |
de | ドイツ語 | いいえ | 2 |
es | スペイン語 | いいえ | 2 |
Odoo のバージョンによる違い
| 機能 | Odoo 14-15 | Odoo 16-17 | Odoo 18-19 |
|---|---|---|---|
| JS 翻訳のインポート | import { _t } from "web.core" | import { _t } from "@web/core/l10n/translation" | 16 と同じ |
| Bootstrap のバージョン | 4.x | 5.1.3(RTL を標準サポート) | 5.1.3 以降 |
| 翻訳の保存先 | ir.translation テーブル | JSON 用語(内部) | JSON 用語 |
| リストのビュータイプ | <tree> | <tree> | <list>(19 のみ) |
| コントローラータイプ | type='json' | type='json' | type='jsonrpc'(19 のみ) |
| 表示属性 | attrs={'invisible': ...} | attrs={'invisible': ...} | インラインの invisible="expr"(19 のみ) |
よくある問題
翻訳が表示されない:-u module --stop-after-init でモジュールを更新し、ブラウザーのキャッシュをクリアしてください。
アラビア語のテキストが文字化けする:ファイルが Latin-1 で保存されています。i18n_converter.py --action convert を実行して文字コードを修正してください。
書式指定子のエラー:msgid と msgstr の %s/%d/%(name)s の数が一致していることを確認してください。
アラビア語ユーザーに Web サイトが英語で表示される:(1)アラビア語がインストールされていること、(2)ユーザーの言語が設定されていること、(3)翻訳追加後にモジュールが更新されていることを確認してください。
Fuzzy エントリ:.po を開いて翻訳を確認し、承認済みエントリから #, fuzzy フラグを削除してください。
ブランディングの設定
生成される .pot/.po ファイルでは、作成者名とメールアドレスを設定できます。環境変数を設定します:
export ODOO_I18N_COPYRIGHT="Your Company"
export ODOO_I18N_BUGS_EMAIL="[email protected]"
詳細リファレンス(メモリファイル)
このスキルの概要を超える包括的なパターンについては、プラグインに次のメモリファイルが含まれています。
memories/translation_patterns.md-- Python の_()/_lt()パターン、XML 属性の翻訳、JS の_t()パターン、.po ファイルの構造、メールテンプレートの翻訳memories/rtl_patterns.md-- RTL の有効化、Bootstrap RTL、CSS の論理プロパティ、SCSS のオーバーライド、RTL での Flexbox、JS による RTL の検出、QWeb レポートの RTL、一般的な RTL の修正memories/language_codes.md-- 言語コード、日付/時刻の形式、数値の形式、通貨表示、ヒジュラ暦に関する注記、タイムゾーンのリファレンス