KilimcininKorOglu/claude-code-mods/tree/main/plugins/i18n-watch
i18n-watch
翻訳キーを呼び出す編集後、JSON、Laravel PHP、YAML、または gettext ロケール ファイルに不足しているキーと、それらのキーが不足している言語に名前を付けます。
この mod について
#i18n-watch
モデルは t('checkout.total') をコンポーネントに追加しますが、キーはロケール ファイルに存在しないか、英語のみに存在します。その後、ページには生のキー、つまりトルコ語ページの英語が表示されますが、ユーザーが気付くまで誰も気づきません。この MOD は、編集で 1 つ以上のロケール ファイルに不足している翻訳キーが使用されるときにモデルに通知します。ノートには編集の結果が付属しているため、モデルは同じターンでキーを追加します。デフォルトでは何も停止されません。 deny モードでは、キーが欠落しているとコミット、プッシュ、マージが停止します。
何をするのか
1。この MOD は編集ツールと書き込みツールをフックします。ソース ファイル (.ts、.tsx、.js、.jsx、.mjs、.cjs、.vue、.svelte、.astro、.php、.py、.rb) の呼び出しが成功した後、 .erb、.haml、.slim)、追加された編集呼び出し (old_string にない new_string 内の翻訳呼び出し、または Write のすべての呼び出し) を読み取ります。
2。読み取られる呼び出しは、最初の引数が引用符で囲まれた t、$t、i18n.t、__、trans、trans_choice、@lang、_、gettext、および ngettext であり、this. の後にもあります。 vm.、i18n.、$i18n.、I18n.、i18n.global.。変数引数、テンプレート リテラル、Rails 遅延キー (t('.title')) はスキップされます。
3。セッション ディレクトリのこれらのディレクトリの下にあるロケール ファイル (最大 4 レベルの深さ) と 200 ファイルを読み取り、node_modules および 2 MB 上のファイルをスキップします: locales、lang、i18n、translations、locale、 t('checkout.total')Q、resources/lang、src/locales、src/i18n、public/locales。セッション ディレクトリはセッションが開始されたディレクトリであり、Bash cd はセッション自体のディレクトリを移動するため、セッションの開始時に 1 回読み取られます。編集されたファイルは、セッションが開始された git リポジトリに基づいて名前が付けられるため、apps/web で開かれたセッションでは、apps/api のファイルに apps/api/x.ts という名前が付けられます。 git リポジトリの外側では、ファイルはセッション ディレクトリに基づいて名前が付けられます。そのルートは、セッションの開始時にも一度読み取られます。
|フォーマット |パスの例 |キー |
|---|---|---|
| JSON (i18next、vue-i18n、Laravel) | locales/tr.json、locales/tr/checkout.json、lang/tr.json |ネストされたキーは点線のパスとして表示されます。 item_one は item も定義します。
| PHP配列(Laravel) | lang/tr/messages.php | messages.key、点線のパスとしてネストされた配列 |
| YAML (Rails、Symfony) | config/locales/tr.yml、translations/messages.tr.yaml |点線のパス。 Rails のトップキー (tr:) が省略されています。
|テキストを取得する | locale/tr/LC_MESSAGES/django.po |各 msgid |
言語はディレクトリ (tr/、en-US/) またはファイル名 (tr.json、messages.tr.yaml) から取得されます。名前空間ファイル内のキーも ns.key および denyQ としてカウントされます。4。言語にキーが存在しない場合、またはキーが存在する言語がない場合、キーは存在しません。各キーには、そのキーが呼び出される行に基づいて名前が付けられているため、キーを開くことができます。モデルは、編集の結果の後に次のメモを読み取ります。
i18n-watch: this edit uses translation keys the locale files lack: checkout.total:42 (missing in tr, de) · checkout.vat:58 (missing in every locale). Add them to each locale file.
最大でも 10 キーに名前が付けられ、残りはカウントされます。この編集で追加されたキーのみが報告されます。以前に報告されたキーは、再度言われることなく調査結果に残ります。 5。同時に 1 行がトランスクリプトに到達するので、モデルが何を話したかがわかります。この行には、指示がなくても、ファイルとそのキーが保持されます。このファイルの名前は、モデルが編集を参照し、あなたが編集を参照しなかったために付けられました。
i18n-watch: keys srcQXZKQZXDAQ.vue uses that the locale files lack: checkout.total:42 (missing in tr, de) · checkout.vat:58 (missing in every locale)
ノートとラインは別個のチャネルです。モデルがラインを読むことはなく、あなたがノートを読むこともありません。
6。 サイドバー が開いている間、これらのキーはストリームのエントリとして代わりにそこに移動します。ファイルが最初に、次にキーごとに 1 行です。キーは赤、その行番号は淡く、every locale は赤、いくつかのロケールのリストは黄色です。トランスクリプトはきれいなままです。エントリは、新しいエントリがペインから押し出すまで残ります。サイドバーが閉じている場合、またはその MOD がインストールされていない場合、トランスクリプト行は上記のように記述されます。
7。発見は決して記憶に残る答えではありません。保持するキーはクレームであり、メジャーごとにディスクからソース ファイルを再度読み取り、呼び出されなくなったキーを削除します。したがって、検出結果は 2 つの方法で終了します。これは、各編集と書き込みの後、各メインループ ターンの終わり、およびガードされた git コマンドの前に測定されます。
- すべてのロケールがキーを取得しました。
- 編集により文字列が削除されたり、別の文字列に置き換えられたり、別のファイルに移動されたりしたため、コードはそれらの呼び出しを停止しました。ファイルが失われると、その検索結果も閉じられます。
エントリがクリアされ、緑色のエントリが 2 つのエントリのどちらであるかを示します。
i18n-watch: every locale now has the keys srcQXZKQZXDCQ.vue lacked: checkout.total · checkout.vat
i18n-watch: index.php no longer uses: Unauthorized Access
サイドバーを閉じると、同じテキストが 1 つのトランスクリプト行になります。モデルはこれについて何も読み取りません。つまり、発見はそれ自体の作業によって閉じられているため、メモは直前に実行したことを繰り返すだけです。ファイルが存在していても読み取れない場合、ファイルが読み取られていないことは何も証明しないため、検索結果はそのまま残ります。
8。モデルが閉じなかった検出結果は、メイン ループの各ターンの終わりに再度測定され、残ったものは次のプロンプトを伴う 1 つの音符としてモデルに届きます。
.tsxQ
プロンプトごとに 1 つではなく、ターンごとに 1 つのノートです。これがなければ、結果は編集時に一度言われ、モデルがそれを忘れている間にペインに立つことになります。新しいことは何も読み取れません。ペインにはすでに同じ結果が記載されています。9。 deny モードでは、ファイルがロケール ファイルに不足しているキーをまだ使用している間、MOD は git commit、git push、および git merge も停止します。 --dry-run、--help、または -h を含むコマンドは停止されません。 git commit は、それ自身のファイルのみに対して応答します。MOD はインデックス (git diff --cached --name-only -z) を読み取り、開いているファイルが 1 つも保持されていない場合にコミットを実行させます。残りのファイル数を 1 行で指定します。 push と merge には読み取るインデックスが保持されていないため、すべての結果がそのまま残ります。バイパスはありません。 /i18n-watch mode note でゲートをオフにするだけです。 note モードはデフォルトであり、何も停止しませんが、git コマンドでの結果を同じように測定するため、確定した結果はペインに残りません。
ロケール ファイルは、それが必要なターンの最初の編集時に読み取られ、ロケール ファイルの編集または書き込み後に再度読み取られます。これらのディレクトリのないプロジェクトには何も得られません。読み取りまたは解析できないロケール ファイルはスキップされ、セッションごとに 1 回ログに記録されます。
ライブチェックでは、モデルは locales/en.json と locales/tr.json を含むプロジェクトのファイルに t('cart.total') を追加し、編集後のメモを読み、一語ずつ引用しました。
コマンド
QXZKQZXDDQ on or off, the mode, and the files still missing keys
QXZKQZXDEQ on | off on by default
QXZKQZXDFQ mode note note only; the default
QXZKQZXDGQ mode deny a commit, a push and a merge also stop while a key is missing
インストール
claude plugin marketplace add KilimcininKorOgluQXZKQZXDHQ
claude plugin install i18n-watch@kilimcininkoroglu-mods
関数フックは早期アクセスです。Claude 2.1.288 をコード化し、後でデフォルトでロードするため、オンにするものは何もありません。
インストール後
1。Claude Codeを再起動します。
到達できるもの
Claude Code 2.1.283 で claude plugin validate で検証済み:
❯ .QXZKQZXDIQ.ts hooks: session.start, command.run{command=i18n-watch}, turn.start, tool.call{tool=Bash}, turn.complete, prompt.submit, tool.call{tool=Edit}, tool.call{tool=Write}
❯ .QXZKQZXDJQ.ts calls: $.command.register, $.fs.exists (via isDir, usedNow), $.fs.list (via walkLocales), $.fs.read (via loadCatalog, usedNow), $.fs.stat (via isDir), $.process.run (via shownRootOf, stagedPaths), $.session.cwd, $.sidebar.clear (via dropEntry), $.sidebar.set (via toPerson), $.store.get (via readSettings), $.store.set (via runCommand, setMode), $.ui.log (via catalogOf, gate, toPerson)
L2 に到達すると、git を実行してインデックスを読み取ります。
1. Reads: the text of each Edit and Write call; the Bash command text; each reported source file again; the locale directories under the session directory and their files
2. Runs: git rev-parse --show-toplevel once at the session's start, to name files against the repository root; git rev-parse --show-toplevel and git diff --cached --name-only -z, at a guarded command in deny mode, to read which files the commit holds
3. Sends: a note to the model after an edit that uses missing keys, one more with the next prompt while a finding stands, and one line to the transcript; nothing leaves the machine
4. Persists: in $.store, the onQXZKQZXDKQ setting and the mode; the locale keys live in memory for one turn
5. Hostile input: locale files are only parsed as data (JSON.parse and line regexes), never run; PHP files are not executed
制限
- セッション ディレクトリの下にあるロケール ディレクトリのみが読み取られます。ロケールが
apps/web/src/localesにあるモノリポジトリは、セッションがリポジトリ ルートで開始されるときには表示されません。 - Laravel PHP ファイルは実行ではなく 1 行ずつ読み取られます。1 行で開閉される配列、計算されたキー、および
included 配列は表示されません。 ・YAMLはインデントで読み込まれます。アンカー、エイリアス、およびフロー マッピング ({a: b}) は従いません。 - 実行時に作成されるキー (
t(name)、t(`a.${b}`)) はチェックされません。 - 言語コードは、オプションの地域またはスクリプトを含む 2 文字です (
tr、.tsQ、zh-Hant)。filなどの 3 文字コードは認識されません。 - 編集でのみ移動するキー (
old_stringにもありました) はチェックされず、Bash を介した編集もチェックされません。 denyモードにはバイパスがありません。所見を修正できない場合は、/i18n-watch mode noteでゲートをオフにします。- ゲートはコマンドテキストを読み取ります。
git commitを非表示にするスクリプトまたはエイリアスを介したコミットは停止されません。 git commit -a、-am、および--の後のパス指定を持つコミットは、インデックスがまだ保持していないファイルをコミットするため、インデックスに絞り込まれません。未解決の発見はすべてそれらを表しています。- インデックスはコマンドの実行前に読み取られます。読み取りと実行 (その間にステージングされる別のプロセス) の間にファイルが変更されるコミットは、読み取り時にインデックスが保持していたものと比較して測定されます。- 検出結果は、ロケール ファイル自体の使用によってではなく、ファイルが行う呼び出しによって閉じられます。コードが呼び出しを停止したキーは、ロケール ファイルにキーがまだ存在しない場合でも、それを呼び出すものはもう存在しないため、検出結果から削除されます。
開発
make install # eslint, typescript-eslint, typescript
make lint # complexity limit 10, the build fails above it
make typecheck # needs .claudeQXZKQZXDLQ/ from QXZKQZXDMQ
make validate
make test # claude plugin test
インストール
まず作者の README で marketplace とプラグイン名を確認してください。コマンドはリポジトリの構成によって変わる場合があります。
claude plugin marketplace add KilimcininKorOglu/claude-code-mods claude plugin install i18n-watch
原文 / README
i18n-watch
The model adds t('checkout.total') to a component, and the key exists in no locale file, or in English only. The page then shows the raw key, or English on the Turkish page, and nobody notices until a user does. This mod tells the model when an edit uses translation keys that one or more locale files lack. The note comes with the Edit's result, so the model adds the keys in the same turn. By default nothing is stopped; in deny mode a commit, a push and a merge stop while a key is missing.
What it does
-
The mod hooks the Edit and Write tools. After a successful call on a source file (
.ts,.tsx,.js,.jsx,.mjs,.cjs,.vue,.svelte,.astro,.php,.py,.rb,.erb,.haml,.slim), it reads the translation calls the edit added: those innew_stringthatold_stringdoes not have, or every call of a Write. -
The calls read are
t,$t,i18n.t,__,trans,trans_choice,@lang,_,gettextandngettextwith a quoted first argument, also afterthis.,vm.,i18n.,$i18n.,I18n.andi18n.global.. A variable argument, a template literal and a Rails lazy key (t('.title')) are skipped. -
It reads the locale files under these directories of the session directory, at most 4 levels deep and 200 files, skipping
node_modulesand any file over 2 MB:locales,lang,i18n,translations,locale,config/locales,resources/lang,src/locales,src/i18n,public/locales. The session directory is the one the session started in, read once at its start, because a Bashcdmoves the session's own directory. The edited file is named against the git repository the session started in, so a session opened inapps/webnames a file ofapps/apiasapps/api/x.ts. Outside a git repository the file is named against the session directory. That root is read once at the session's start too.| Format | Example path | Keys | |---|---|---| | JSON (i18next, vue-i18n, Laravel) |
locales/tr.json,locales/tr/checkout.json,lang/tr.json| nested keys as dotted paths;item_onealso definesitem| | PHP array (Laravel) |lang/tr/messages.php|messages.key, nested arrays as dotted paths | | YAML (Rails, Symfony) |config/locales/tr.yml,translations/messages.tr.yaml| dotted paths; a Rails top key (tr:) is left out | | gettext |locale/tr/LC_MESSAGES/django.po| eachmsgid|The language comes from a directory (
tr/,en-US/) or from the file name (tr.json,messages.tr.yaml). A key in a namespace file also counts asns.keyandns:key. -
A key is missing when a language lacks it, or when no language has it. Each key is named with the line it is called on, so you can open it. The model reads this note after the Edit's result:
i18n-watch: this edit uses translation keys the locale files lack: checkout.total:42 (missing in tr, de) · checkout.vat:58 (missing in every locale). Add them to each locale file.At most 10 keys are named, the rest counted. Only the keys this edit added are reported; a key reported before stays in the finding without being said again.
-
At the same moment one line reaches the transcript, so you see what the model was told. The line holds the file and its keys, without the instruction. The file is named because the model saw the edit and you did not:
i18n-watch: keys src/Cart.vue uses that the locale files lack: checkout.total:42 (missing in tr, de) · checkout.vat:58 (missing in every locale)The note and the line are separate channels: the model never reads the line, and you never read the note.
-
While the sidebar is open, those keys go there instead, as an entry in its stream: the file first, then one line per key, with the key red, its line number faint,
every localered and a list of some locales yellow. The transcript stays clean. The entry stays until newer ones push it off the pane. With the sidebar closed, or without that mod installed, the transcript line is written as above. -
A finding is never a remembered answer. The keys it holds are a claim, and every measure reads the source file from disk again and drops the keys it no longer calls. So a finding closes two ways, measured after each Edit and Write, at the end of each main-loop turn, and before a guarded git command:
- every locale gained the keys;
- the code stopped calling them, because the edit deleted the string, replaced it with another one or moved it to another file. A file that is gone closes its finding too.
The entry is cleared and a green one says which of the two it was:
i18n-watch: every locale now has the keys src/Cart.vue lacked: checkout.total · checkout.vat i18n-watch: index.php no longer uses: Unauthorized AccessWith the sidebar closed the same text is one transcript line. The model reads nothing of this: the finding closed by its own work, so a note would only repeat what it just did. A file that is there and cannot be read keeps its finding, because an unread file proves nothing.
-
A finding the model did not close is measured again at the end of each main-loop turn, and what is left reaches the model as one note with its next prompt:
i18n-watch: 1 file(s) still use translation keys the locale files lack: index.php (Unauthorized Access:42). Add the keys to every locale file, or take the calls out.One note per turn, not one per prompt. Without this the finding would be said once, at the edit, and then stand in the pane while the model forgot it. You read nothing new: the pane already carries the same finding.
-
In
denymode the mod also stopsgit commit,git pushandgit mergewhile a file still uses keys the locale files lack; a command with--dry-run,--helpor-his not stopped. Agit commitanswers for its own files alone: the mod reads the index (git diff --cached --name-only -z) and lets the commit run when it holds none of the open files, with one line to you naming how many still stand. Apushand amergehold no index to read, so every finding stands there. There is no bypass; only you turn the gate off, with/i18n-watch mode note.notemode is the default and stops nothing, but it measures the findings at a git command all the same, so a settled one does not stay in the pane.
The locale files are read at the first edit of a turn that needs them, and again after an Edit or Write of a locale file. A project without these directories gets nothing. A locale file that cannot be read or parsed is skipped and logged once per session.
In the live check the model added t('cart.total') to a file of a project with locales/en.json and locales/tr.json, read the note after the Edit, and quoted it word for word.
Command
/i18n-watch on or off, the mode, and the files still missing keys
/i18n-watch on | off on by default
/i18n-watch mode note note only; the default
/i18n-watch mode deny a commit, a push and a merge also stop while a key is missing
Install
claude plugin marketplace add KilimcininKorOglu/claude-code-mods
claude plugin install i18n-watch@kilimcininkoroglu-mods
Function hooks are early access. Claude Code 2.1.288 and later load them by default, so there is nothing to switch on.
After installing
- Restart Claude Code.
What it can reach
Validated with claude plugin validate on Claude Code 2.1.283:
❯ ./register.ts hooks: session.start, command.run{command=i18n-watch}, turn.start, tool.call{tool=Bash}, turn.complete, prompt.submit, tool.call{tool=Edit}, tool.call{tool=Write}
❯ ./register.ts calls: $.command.register, $.fs.exists (via isDir, usedNow), $.fs.list (via walkLocales), $.fs.read (via loadCatalog, usedNow), $.fs.stat (via isDir), $.process.run (via shownRootOf, stagedPaths), $.session.cwd, $.sidebar.clear (via dropEntry), $.sidebar.set (via toPerson), $.store.get (via readSettings), $.store.set (via runCommand, setMode), $.ui.log (via catalogOf, gate, toPerson)
Reach L2, it runs git to read the index.
1. Reads: the text of each Edit and Write call; the Bash command text; each reported source file again; the locale directories under the session directory and their files
2. Runs: git rev-parse --show-toplevel once at the session's start, to name files against the repository root; git rev-parse --show-toplevel and git diff --cached --name-only -z, at a guarded command in deny mode, to read which files the commit holds
3. Sends: a note to the model after an edit that uses missing keys, one more with the next prompt while a finding stands, and one line to the transcript; nothing leaves the machine
4. Persists: in $.store, the on/off setting and the mode; the locale keys live in memory for one turn
5. Hostile input: locale files are only parsed as data (JSON.parse and line regexes), never run; PHP files are not executed
Limits
- Only the locale directories under the session directory are read. A monorepo whose locales sit in
apps/web/src/localesis not seen when the session starts at the repository root. - A Laravel PHP file is read line by line, not run: an array opened and closed on one line, a computed key and an
included array are not seen. - YAML is read by indent. Anchors, aliases and flow mappings (
{a: b}) are not followed. - A key built at run time (
t(name),t(`a.${b}`)) is not checked. - A language code is two letters with an optional region or script (
tr,pt_BR,zh-Hant); a three-letter code such asfilis not recognised. - A key the edit only moves (it was in
old_stringtoo) is not checked, and neither is an edit through Bash. - The
denymode has no bypass. When a finding cannot be fixed, you turn the gate off with/i18n-watch mode note. - The gate reads the command text. A commit through a script or an alias that hides
git commitis not stopped. - A
git commit -a, a-amand a commit with a pathspec after--are not narrowed to the index, because they commit files the index does not hold yet. Every open finding stands for those. - The index is read before the command runs. A commit whose files change between the read and the run (another process staging meanwhile) is measured against what the index held at the read.
- A finding is closed by the calls the file makes, not by the locale files' own use. A key the code stopped calling is dropped from the finding even when the locale files still lack it, because nothing calls it any more.
Development
make install # eslint, typescript-eslint, typescript
make lint # complexity limit 10, the build fails above it
make typecheck # needs .claude/types/ from /plugin-types
make validate
make test # claude plugin test
