ClaudeMods
☰
KO
● 0 명 접속 중 · 조회 0 회
후원프로젝트 제출
GitHub 저장소 · 작성자 KilimcininKorOglu

i18n-watch

번역 키를 호출하는 편집 후 JSON, Laravel PHP, YAML 또는 gettext 로케일 파일에 없는 키 이름과 이러한 키가 없는 언어의 이름을 지정합니다.

KilimcininKorOglu@KilimcininKorOglu

KilimcininKorOglu/claude-code-mods/tree/main/plugins/i18n-watch

번역 완료

이 mod 소개

#i18n-watch

모델이 t('checkout.total')를 구성요소에 추가하고 키가 로케일 파일에 없거나 영어로만 존재합니다. 그런 다음 페이지에는 터키어 페이지의 원시 키 또는 영어가 표시되며 사용자가 표시할 때까지는 아무도 알 수 없습니다. 이 모드는 편집에서 하나 이상의 로케일 파일에 부족한 번역 키를 사용하는 경우 모델에 알려줍니다. 메모는 편집 결과와 함께 제공되므로 모델은 동일한 차례에 키를 추가합니다. 기본적으로 아무것도 중지되지 않습니다. deny 모드에서는 키가 누락된 동안 커밋, 푸시 및 병합이 중지됩니다.

기능

  1. 모드는 편집 및 쓰기 도구를 연결합니다. 소스 파일(.ts, .tsx, .js, .jsx, .mjs, .cjs, .vue, .svelte, .astro, .php, .py, .rb, .erb, .haml, .slim), 편집이 추가된 번역 호출(old_string에 없는 new_string의 번역 호출 또는 모든 쓰기 호출)을 읽습니다.

  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가 세션 자체 디렉터리를 이동하기 때문에 시작 시 한 번 읽혀집니다. 편집된 파일은 세션이 시작된 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(레일, 심포니) | config/locales/tr.yml, translations/messages.tr.yaml | 점선 경로; Rails 상단 키(tr:)가 빠졌습니다 | | gettext | 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 키의 이름이 지정되고 나머지도 계산됩니다. 이 편집 내용이 추가된 키만 보고됩니다. 이전에 보고된 키는 다시 언급되지 않고 결과에 남아 있습니다.

  4. 동시에 한 줄이 성적표에 도달하므로 모델이 말한 내용을 볼 수 있습니다. 이 줄에는 명령 없이 파일과 해당 키가 포함됩니다. 모델이 편집 내용을 확인했지만 사용자는 이를 확인하지 않았기 때문에 파일 이름이 지정되었습니다.

    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)
    

    메모와 선은 별도의 채널입니다. 모델은 선을 읽지 않으며 사용자도 메모를 읽지 않습니다.

  5. 사이드바가 열려 있는 동안 해당 키는 해당 스트림의 항목으로 대신 거기로 이동합니다. 먼저 파일, 키당 한 줄, 키는 빨간색이고 줄 번호는 희미하며 every locale 빨간색 및 일부 로케일 목록은 노란색입니다. 성적표는 깨끗하게 유지됩니다. 항목은 새로운 항목이 창 밖으로 밀어낼 때까지 유지됩니다. 사이드바가 닫혀 있거나 해당 모드가 설치되지 않은 상태에서 성적표 줄은 위와 같이 작성됩니다.

  6. 발견은 결코 기억되는 답이 아닙니다. 보유한 키는 클레임이며 모든 측정값은 디스크에서 소스 파일을 다시 읽고 더 이상 호출하지 않는 키를 삭제합니다. 따라서 결과는 각 편집 및 쓰기 이후, 각 메인 루프 회전이 끝날 때, 그리고 보호된 git 명령 이전에 측정되는 두 가지 방법으로 종료됩니다.

    • 모든 로케일에서 키를 얻었습니다.
    • 편집으로 인해 문자열이 삭제되거나 다른 문자열로 바뀌거나 다른 파일로 이동했기 때문에 코드 호출이 중단되었습니다. 사라진 파일은 찾은 결과도 닫힙니다.

    항목이 지워지고 두 항목 중 어느 것이었는지 녹색 항목이 표시됩니다.

    i18n-watch: every locale now has the keys srcQXZKQZXDCQ.vue lacked: checkout.total · checkout.vat
    i18n-watch: index.php no longer uses: Unauthorized Access
    

    사이드바를 닫으면 동일한 텍스트가 하나의 기록 줄이 됩니다. 모델은 이에 대해 아무것도 읽지 않습니다. 자체 작업으로 결과가 종결되었으므로 메모는 방금 수행한 작업만 반복합니다. 읽지 않은 파일은 아무 것도 증명하지 못하기 때문에 거기에 있지만 읽을 수 없는 파일은 찾은 내용을 유지합니다.

  7. 모델이 닫히지 않은 결과는 각 메인 루프 회전이 끝날 때 다시 측정되고 남은 내용은 다음 프롬프트와 함께 하나의 메모로 모델에 도달합니다.

.tsxQ 프롬프트당 하나가 아닌 턴당 하나의 메모입니다. 이것이 없으면 결과는 편집 시 한 번만 말한 다음 모델이 잊어버린 동안 창에 서 있을 것입니다. 새로운 내용은 아무것도 읽지 않았습니다. 창에는 이미 동일한 결과가 포함되어 있습니다.9. deny 모드에서 모드는 git commit, git push 및 git merge도 중지하지만 파일은 로케일 파일에 부족한 키를 계속 사용합니다. --dry-run, --help 또는 -h를 사용한 명령은 중지되지 않습니다. git commit는 자체 파일에 대해서만 응답합니다. 모드는 인덱스(git diff --cached --name-only -z)를 읽고 열려 있는 파일이 하나도 없을 때 커밋을 실행하도록 하며, 한 줄에 아직 남아 있는 파일 수를 지정합니다. push 및 merge에는 읽을 색인이 없으므로 모든 결과가 그대로 유지됩니다. 우회가 없습니다. /i18n-watch mode note를 사용하여 게이트를 끄기만 하면 됩니다. note 모드는 기본값이며 아무것도 중지하지 않지만 git 명령에서 결과를 모두 동일하게 측정하므로 확정된 모드는 창에 유지되지 않습니다.

로케일 파일은 필요한 차례의 첫 번째 편집 시 읽혀지고, 로케일 파일의 편집 또는 쓰기 후에 다시 읽혀집니다. 이러한 디렉터리가 없는 프로젝트는 아무것도 얻지 못합니다. 읽거나 구문 분석할 수 없는 로케일 파일은 세션당 한 번씩 건너뛰고 기록됩니다.

실시간 확인에서 모델은 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 Code 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 파일은 실행되지 않고 한 줄씩 읽혀집니다. 한 줄에서 열리고 닫히는 배열, 계산된 키 및 included 배열은 표시되지 않습니다.
  • YAML은 들여쓰기로 읽습니다. 앵커, 별칭 및 흐름 매핑({a: b})은 따르지 않습니다.
  • 런타임에 빌드된 키(t(name), t(`a.${b}`))는 검사되지 않습니다.
  • 언어 코드는 선택적 지역 또는 스크립트(tr, .tsQ, zh-Hant)가 포함된 두 글자입니다. fil와 같은 3자리 코드는 인식되지 않습니다.
  • 편집만 이동하는 키(old_string에도 있음)는 확인되지 않으며 Bash를 통한 편집도 되지 않습니다.
  • deny 모드에는 바이패스가 없습니다. 결과를 수정할 수 없으면 /i18n-watch mode note를 사용하여 게이트를 끕니다.
  • 게이트는 명령 텍스트를 읽습니다. git commit를 숨기는 별칭이나 스크립트를 통한 커밋은 중지되지 않습니다.
  • git commit -a, -am 및 -- 이후 pathspec이 있는 커밋은 인덱스에 아직 보관되지 않은 파일을 커밋하기 때문에 인덱스로 좁혀지지 않습니다. 공개된 모든 결과는 이를 나타냅니다.- 명령이 실행되기 전에 인덱스를 읽습니다. 읽기와 실행(그동안 다른 프로세스 준비) 사이에 파일이 변경되는 커밋은 읽기 시 인덱스에 보관된 내용을 기준으로 측정됩니다.
  • 로케일 파일 자체 사용이 아니라 파일 호출에 의해 결과가 닫힙니다. 코드에서 호출이 중지된 키는 더 이상 호출하는 항목이 없기 때문에 로케일 파일에 키가 부족한 경우에도 결과에서 삭제됩니다.

개발

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

  1. 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 in new_string that old_string does not have, or every call of a Write.

  2. The calls read are t, $t, i18n.t, __, trans, trans_choice, @lang, _, gettext and ngettext with a quoted first argument, also after this., vm., i18n., $i18n., I18n. and i18n.global.. A variable argument, a template literal and a Rails lazy key (t('.title')) are skipped.

  3. It reads the locale files under these directories of the session directory, at most 4 levels deep and 200 files, skipping node_modules and 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 Bash cd moves the session's own directory. The edited file is named against the git repository the session started in, so a session opened in apps/web names a file of apps/api as apps/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_one also defines item | | 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 | each msgid |

    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 as ns.key and ns:key.

  4. 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.

  5. 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.

  6. 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 locale red 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.

  7. 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 Access
    

    With 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.

  8. 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.

  9. In deny mode the mod also stops git commit, git push and git merge while a file still uses keys the locale files lack; a command with --dry-run, --help or -h is not stopped. A git commit answers 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. A push and a merge hold no index to read, so every finding stands there. There is no bypass; only you turn the gate off, with /i18n-watch mode note. note mode 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

  1. 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/locales is 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 as fil is not recognised.
  • A key the edit only moves (it was in old_string too) is not checked, and neither is an edit through Bash.
  • The deny mode 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 commit is not stopped.
  • A git commit -a, a -am and 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

비슷한 프로젝트