copy_tuner_client 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/copy_tuner_client/version.rb +1 -1
- data/skills/copy-tuner/SKILL.md +32 -21
- data/skills/copy-tuner-to-locales-cleanup/SKILL.md +165 -0
- data/skills/copy-tuner-to-locales-cleanup/references/example-touchpoints.md +111 -0
- data/skills/copy-tuner-to-locales-cleanup/references/verification-final.md +73 -0
- data/skills/copy-tuner-to-locales-migrate-prefix/SKILL.md +265 -0
- data/skills/copy-tuner-to-locales-migrate-prefix/references/example-touchpoints.md +126 -0
- data/skills/copy-tuner-to-locales-migrate-prefix/references/export-and-split.md +126 -0
- data/skills/copy-tuner-to-locales-migrate-prefix/references/local-first-regexp.md +72 -0
- data/skills/copy-tuner-to-locales-migrate-prefix/references/verification-per-prefix.md +63 -0
- data/skills/copy-tuner-to-locales-migrate-prefix/scripts/migrate_prefix.rb +279 -0
- metadata +10 -1
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: copy-tuner-to-locales-migrate-prefix
|
|
3
|
+
description: >-
|
|
4
|
+
copy_tuner(CopyTuner / copy_tuner_client)で集中管理している i18n データを、prefix(正規表現)単位で
|
|
5
|
+
Rails 標準の config/locales(YAML)管理へ段階移行するスキル。gem の local_first_key_regexp を使い、
|
|
6
|
+
1 回につき 1 prefix をローカルへ寄せて regexp に積み上げる。全 prefix 完了後の gem 撤去は
|
|
7
|
+
copy-tuner-to-locales-cleanup スキルで行う。
|
|
8
|
+
disable-model-invocation: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# copy_tuner → config/locales 段階移行スキル(prefix 単位)
|
|
12
|
+
|
|
13
|
+
copy_tuner(`copy_tuner_client` gem)で集中管理している i18n データを、**prefix(正規表現)単位で**少しずつ
|
|
14
|
+
Rails 標準の `config/locales` 配下の YAML 管理へ移していくためのワークフロー。**1 回の実行で 1 prefix だけ**
|
|
15
|
+
移行し、これを繰り返す。全 prefix の移行が完了したら `copy-tuner-to-locales-cleanup` スキルで gem・CI・
|
|
16
|
+
deploy・docs・MCP をまとめて撤去する。
|
|
17
|
+
|
|
18
|
+
このスキルは**特定のリポジトリに依存しない**。project_id・ファイルパス・CI 構成はプロジェクトごとに異なるので、
|
|
19
|
+
固有値を覚えるのではなく**毎サイクル、自分が編集する箇所(initializer の regexp・config/locales)を探索して
|
|
20
|
+
見つけ直す**(手順 2)。種別ごとの典型例は `references/example-touchpoints.md` を参照。
|
|
21
|
+
|
|
22
|
+
## なぜ prefix 単位で段階移行するのか
|
|
23
|
+
|
|
24
|
+
一発で全 i18n をローカル化すると、移行漏れ(ローカル YAML に書き忘れたキー)が**一斉に未訳化**して事故になる。
|
|
25
|
+
prefix 単位なら、移した範囲だけが影響を受け、移行漏れはその範囲の未訳として小さく顕在化する。安全な prefix から
|
|
26
|
+
順に潰していける。
|
|
27
|
+
|
|
28
|
+
### 前提となる gem 機能(local_first_key_regexp)
|
|
29
|
+
|
|
30
|
+
[copy-tuner-ruby-client #110](https://github.com/SonicGarden/copy-tuner-ruby-client/pull/110) で追加された
|
|
31
|
+
`local_first_key_regexp` を使う。挙動の要点(`references/local-first-regexp.md` に詳細):
|
|
32
|
+
|
|
33
|
+
- **locale を除いたキー**(`views.foo` 等)が regexp にマッチすると、`I18nBackend#lookup` は CopyTuner
|
|
34
|
+
キャッシュもアップロードキューも**一切見ず**、Rails 標準バックエンド(`I18n::Backend::Simple`)に委譲して
|
|
35
|
+
ローカル YAML だけを引く。これを**完全分離**と呼ぶ。
|
|
36
|
+
- 完全分離なので、**マッチキーがローカル YAML に無ければ即 `nil`(未訳)**。CopyTuner へフォールバックしない。
|
|
37
|
+
これが「移行漏れを未訳として顕在化させる」仕組み。
|
|
38
|
+
- マッチしないキーは従来どおり CopyTuner キャッシュ優先 → 無ければローカル、という動作のまま。
|
|
39
|
+
- regexp は**単一**(配列非対応)。複数 prefix は `Regexp.union` で 1 本に積み上げる。
|
|
40
|
+
|
|
41
|
+
gem を残したまま regexp に prefix を足していくだけなので、移行途中でも CopyTuner と config/locales が安全に
|
|
42
|
+
共存する。
|
|
43
|
+
|
|
44
|
+
## ワークフロー(1 サイクル = 1 prefix)
|
|
45
|
+
|
|
46
|
+
### 1. gem 前提確認
|
|
47
|
+
|
|
48
|
+
`local_first_key_regexp` が使えるバージョンの `copy_tuner_client` が入っているか確認する。
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
bin/rails runner 'p CopyTunerClient.configuration.respond_to?(:local_first_key_regexp)'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`true` でなければこのスキルは使えない。gem を PR #110 が入ったバージョンへ上げてから(`Gemfile` 更新 →
|
|
55
|
+
`bundle update copy_tuner_client`)出直す。**バージョンアップはこのスキルの前提条件**であり、ここで止める。
|
|
56
|
+
|
|
57
|
+
### 2. 編集対象の場所を確認(毎サイクル)
|
|
58
|
+
|
|
59
|
+
このスキルが**実際に編集するのは次の箇所だけ**なので、毎サイクル開始時にこれらの場所を軽く確認する。
|
|
60
|
+
grep 結果はセッションをまたいで残らない(複数セッションに分割して進める前提)ため、「初回に把握したはず」に
|
|
61
|
+
頼らず毎回見つけ直す。`vendor/`・`tmp/`・`node_modules/`・`Gemfile.lock` は除外する。
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 毎サイクル触る: initializer の local_first_key_regexp と config/locales の採番慣習
|
|
65
|
+
git grep -nI 'local_first_key_regexp' -- ':!vendor' ':!tmp' ':!node_modules'
|
|
66
|
+
ls config/locales
|
|
67
|
+
|
|
68
|
+
# 初回だけ触る(手順 9・10 用): CI の export ステップと i18n 方針ドキュメント
|
|
69
|
+
git grep -nI -e 'copy_tuner:export' -e 'CopyTuner' -- '.github/' 'doc/' 'CLAUDE.md'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- 手順 6・7 で毎回触る **initializer の `local_first_key_regexp`** の位置と、**`config/locales/`** の採番慣習
|
|
73
|
+
(例: `00_`・`10_`)を確認する。
|
|
74
|
+
- 手順 9(CI の export ステップ削除)・手順 10(方針ドキュメントの中間状態更新)で**初回だけ**触る箇所も
|
|
75
|
+
ここで場所だけ押さえる。
|
|
76
|
+
|
|
77
|
+
#### 2-1. (初回のみ)既存 locales を `0000_original_` プレフィックスへリネーム
|
|
78
|
+
|
|
79
|
+
このスキルの分割方針(手順 6)は、**既存 `config/locales` をロード最先頭に固定し、移行で足すファイルを後ろに
|
|
80
|
+
置いて Rails i18n の後勝ちで上書きする**ことを前提にする。そのため**初回サイクルの最初に一度だけ**、既存の
|
|
81
|
+
locales ファイルを `0000_original_` プレフィックスへリネームする。
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# 例(既存ファイル名に合わせて読み替える):
|
|
85
|
+
git mv config/locales/00_ja.yml config/locales/0000_original_ja.yml
|
|
86
|
+
git mv config/locales/00_devise.ja.yml config/locales/0000_original_devise.ja.yml
|
|
87
|
+
git mv config/locales/10_app.yml config/locales/0000_original_app.yml
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- **初回判定**: `ls config/locales` に `0000_original_` で始まるファイルが既にあれば、このリネームは済んでいる
|
|
91
|
+
のでスキップする(2 サイクル目以降は常にスキップ)。
|
|
92
|
+
- `0000_` は数値プレフィックスで必ず最先頭ロードになる。以降 migrate で足すファイルは `0010_` 以降に置き
|
|
93
|
+
(手順 6)、ロード順で後勝ち=オリジナルを上書きする。`Regexp.union` の積み上げ(手順 7)と合わせ、
|
|
94
|
+
「重複キーは export 側を正とする」を**手作業マージなしで構造的に保証**するのがこの固定の狙い。
|
|
95
|
+
- このリネームは**ファイルの中身を一切変えない**(純粋にロード順を確定するだけ)。リネーム後に rspec を流し、
|
|
96
|
+
`translation missing` が**増えていない**ことだけ確認する。
|
|
97
|
+
|
|
98
|
+
gem・CI の deploy ワークフロー・deploy フック・MCP 設定の**撤去**は `copy-tuner-to-locales-cleanup` の仕事で、
|
|
99
|
+
cleanup は自前で touchpoint を grep し直す。**このスキルでそれらを棚卸し・編集する必要はない**。種別ごとの
|
|
100
|
+
典型的な在処は `references/example-touchpoints.md` を参照。
|
|
101
|
+
|
|
102
|
+
### 3. 残 prefix の把握
|
|
103
|
+
|
|
104
|
+
全件を export して俯瞰し、移行済み(現在の `local_first_key_regexp` がマッチする)prefix と未移行 prefix を
|
|
105
|
+
一覧化する。export は一時ファイルへ書く(`tmp/` 等の捨て場)。
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
bundle exec rake copy_tuner:export[tmp/copy_tuner_all.yml]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
このタスクは内部で `CopyTunerClient.cache.sync` を呼び、サーバから最新を取得してから全 blurb を書き出す
|
|
112
|
+
(全件取得の唯一確実な手段。詳細は `references/export-and-split.md`)。出力 YAML のトップセクションを眺めて、
|
|
113
|
+
どの prefix が残っているかを確認する。
|
|
114
|
+
|
|
115
|
+
### 4. 対象 prefix の選定
|
|
116
|
+
|
|
117
|
+
残 prefix から **1 つ**選ぶ。影響が小さく構造が安定したものから始め、最後に大物(`views`)を回す:
|
|
118
|
+
|
|
119
|
+
1. **gem 由来(最安全・先行)**: `devise` / `good_job` / `ice_cube` / `restrict_dependent_destroy` 等。
|
|
120
|
+
値が安定しアプリ実装に依存しにくい。
|
|
121
|
+
2. **Rails 標準フォーマット**: `date` / `time` / `datetime` / `number` / `helpers` / `text`。
|
|
122
|
+
ただし**非表現値**(配列・シンボル・数値)の注意あり(手順 6)。
|
|
123
|
+
3. **バリデーションメッセージ**: `activerecord.errors` / `activemodel.errors`。テストで検知しやすい。
|
|
124
|
+
4. **モデル名・カラム名**: `activerecord.models` / `activerecord.attributes` / `activemodel.attributes` /
|
|
125
|
+
`activerecord.enums`。プロジェクトの i18n 方針で「新規キー登録の例外」とされていることが多い
|
|
126
|
+
(プロジェクトの i18n 方針ドキュメントでそう規定されていることが多い)。**全撤去がゴールなのでこの prefix も最終的に移行対象に含める**。
|
|
127
|
+
例外規定の撤廃は cleanup で行う。
|
|
128
|
+
5. **画面テキスト(最大・最後)**: `views` / `text`。量が多く画面影響が大きいので最後に回し、画面確認の比重を
|
|
129
|
+
上げる。1 回が大きすぎるなら `views.<controller>.` の 2 階層目で更に刻んでよい(regexp を `\Aviews\.users\.`
|
|
130
|
+
のように書ける)。
|
|
131
|
+
|
|
132
|
+
### 5. 不正キーの事前チェック(関門)
|
|
133
|
+
|
|
134
|
+
export 済み YAML を config/locales に持ち込む前に、不正キーがないことを確認する。
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
bundle exec rake copy_tuner:detect_conflict_keys
|
|
138
|
+
bundle exec rake copy_tuner:detect_html_incompatible_keys
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- `detect_conflict_keys` … キー衝突。`foo` という値キーと `foo.bar` というネストキーが同居すると YAML へ
|
|
142
|
+
正しく展開できない。
|
|
143
|
+
- `detect_html_incompatible_keys` … `html_escape` 有効環境で `.html` 慣習と矛盾する値など。
|
|
144
|
+
|
|
145
|
+
これらのタスクは**全キー対象**で prefix 絞り込み引数は無い。**出力のうち今回の対象 prefix に該当する行だけ**を
|
|
146
|
+
関門にする(対象外 prefix の不正キーは、その prefix を移す回まで保留してよい)。該当があれば**そのまま
|
|
147
|
+
config/locales に持ち込むと壊れる**ので、一覧をユーザーに報告し、copy_tuner の管理画面側で修正してもらってから
|
|
148
|
+
進む。(タスクが見つからない場合は `bundle exec rake -T copy_tuner` で確認。)
|
|
149
|
+
|
|
150
|
+
### 6. 対象 prefix を config/locales へ配置(スクリプトで一気通貫)
|
|
151
|
+
|
|
152
|
+
配置・移行漏れ検証・オリジナルからの削除は決定論的なので、手作業でなく `scripts/migrate_prefix.rb` を
|
|
153
|
+
`bin/rails runner` で実行する。**1 本のスクリプトで配置 → 静的ガード → 移行漏れ検証 → オリジナル削除まで**
|
|
154
|
+
一気通貫で行い、漏れが 1 件でもあれば**オリジナルを一切変更せず中断**する。
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
bin/rails runner .claude/skills/copy-tuner-to-locales-migrate-prefix/scripts/migrate_prefix.rb \
|
|
158
|
+
-- --prefix date --export tmp/copy_tuner_all.yml --out config/locales/0010_date.yml
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- `--prefix` … 今回移行する prefix(ドット区切り。`date` / `activerecord.attributes` 等)。
|
|
162
|
+
- `--export` … 手順 3 で出した全件 export YAML。
|
|
163
|
+
- `--out` … 移行分の配置先。**オリジナル(`0000_original_*.yml`)より後にロードされる採番**(`0010_` 以降)。
|
|
164
|
+
採番慣習は手順 2 で確認したものに合わせる。
|
|
165
|
+
- `--regexp` … 省略時は prefix から `/\A<prefix>\./` を自動生成(手順 7 の `local_first_key_regexp` と整合)。
|
|
166
|
+
2 階層目で刻む(`views.users` 等)ときだけ明示する。
|
|
167
|
+
- `--locales` … 省略時は `I18n.available_locales`(`default_locale` を先頭)を対象 locale にする。`--locales ja,en`
|
|
168
|
+
のように明示すると上書きできる(fixture を使った検証用)。スクリプトは対象 locale すべてを横断して配置・
|
|
169
|
+
検証・削除する(単一ロケール運用でも、将来 locale を足しても自動追従する)。
|
|
170
|
+
|
|
171
|
+
スクリプトの動作(詳細・設計判断は `references/export-and-split.md`):
|
|
172
|
+
|
|
173
|
+
配置・検証・削除は対象 locale(`--locales`/既定は `I18n.available_locales`)ごとに独立して行い、`--out` には
|
|
174
|
+
全 locale のサブツリー(`ja:` / `en:` …)を書き出す。あるロケールに当該 prefix のキーが無ければ warn して
|
|
175
|
+
そのロケールはスキップする。
|
|
176
|
+
|
|
177
|
+
1. **配置**: オリジナル全ファイルから対象 prefix サブツリーを抽出し(ファイル名昇順=ロード順で deep merge)、
|
|
178
|
+
export サブツリーを**その上に deep merge**(String blurb は export 勝ち)、最後に**オリジナル由来の非表現値
|
|
179
|
+
(配列・シンボル・数値・真偽値)を再適用**して `--out` へ書き出す(`deep_merge(deep_merge(orig, exp), non_blurb)`)。
|
|
180
|
+
「export を正とする」を満たしつつ、**非表現値は orig 値が必ず勝つ**(export 側に壊れた非表現値が出ても置換
|
|
181
|
+
されない。後述)。
|
|
182
|
+
2. **静的ガード**: YAML ラウンドトリップ一致・`--out` が `config/locales` 配下の `.yml`(次回起動の i18n glob で
|
|
183
|
+
ロードされる場所)・全 leaf キーが regexp にマッチ、を確認(採番ミス・regexp 不一致・YAML 崩れの早期検出)。
|
|
184
|
+
3. **移行漏れ検証**: オリジナル削除を**メモリ上でシミュレート**し、削除後ツリーを素の `I18n::Backend::Simple` に
|
|
185
|
+
載せて対象 prefix の全キーを実 lookup。`translation missing` になるキーがあれば漏れ。
|
|
186
|
+
4. **ゲート**: 漏れゼロのときだけオリジナルから該当サブツリーを削除(空親も刈る)。漏れがあれば中断。
|
|
187
|
+
|
|
188
|
+
**非表現値が必ず orig 値で残る**: copy_tuner は flat な文字列 blurb しか持てないため、配列・シンボル・数値・
|
|
189
|
+
真偽値(`date.order` の `:year`、`date.*_names`、`number.*.precision`/`*.significant` 等)は export に出てこない
|
|
190
|
+
/壊れて(文字列化して)出てくる可能性がある。スクリプトは export を上書きした**後に**、オリジナル由来の
|
|
191
|
+
非表現値(非 String leaf)を再適用するので、**export 側に壊れた値が出ても orig の正値が置換勝ちする**。同じ
|
|
192
|
+
prefix 内で `date.formats`(文字列・export 勝ち)と `date.order`(シンボル配列・orig 勝ち)が住み分く。現スキルが
|
|
193
|
+
以前使っていた `0005_rails_non_blurb.yml` への別隔離は**不要**(このスクリプトに吸収済み)。
|
|
194
|
+
|
|
195
|
+
> NOTE: 削除は手順 8 ではなく**このスクリプト内で**完結する(移行漏れ検証を通った場合のみ)。オリジナルを
|
|
196
|
+
> 残したまま検証しても、オリジナルが漏れを埋めてしまい未訳検知が無意味になるため、検証と削除を同一スクリプトに
|
|
197
|
+
> 束ねている。スクリプトが中断した場合は `--out` のファイルだけが残る(オリジナルは無傷)ので、原因を直して
|
|
198
|
+
> 再実行するか `--out` を消してやり直す。
|
|
199
|
+
|
|
200
|
+
### 7. local_first_key_regexp に prefix を追加
|
|
201
|
+
|
|
202
|
+
initializer(`config/initializers/copy_tuner.rb` 等)の `CopyTunerClient.configure` ブロックで、
|
|
203
|
+
`local_first_key_regexp` を `Regexp.union` で組み直し、今回の prefix を 1 本足す。
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
config.local_first_key_regexp = Regexp.union(
|
|
207
|
+
/\Adevise\./,
|
|
208
|
+
/\Aice_cube\./,
|
|
209
|
+
/\Aviews\./, # ← 今回追加した prefix
|
|
210
|
+
)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**必ず `\A` でアンカーする**(`views` が `reviews` に部分マッチする事故を防ぐ。キーは locale 除去後なので
|
|
214
|
+
`\A` 起点で良い)。詳細・なぜ単一 Regexp なのかは `references/local-first-regexp.md`。
|
|
215
|
+
|
|
216
|
+
### 8. 検証(任意・ユーザー判断)
|
|
217
|
+
|
|
218
|
+
手順 6 のスクリプトが**移行漏れ(削除後に未訳化するキー)がゼロであることを機械的に確認した上で削除**まで
|
|
219
|
+
済ませている(メモリ上で削除をシミュレートし、素の `I18n::Backend::Simple` で対象 prefix の全キーを実 lookup)。
|
|
220
|
+
そのためスキルとしての rspec/画面確認は**必須にしない**。すべて git 管理下なので、問題があれば戻せる。
|
|
221
|
+
|
|
222
|
+
ただしスクリプト内の検証は**静的キー集合とロード経路**までしか見ない。次の**実行時コンテキスト依存**の範囲は
|
|
223
|
+
カバーしないので、必要に応じてユーザー判断で確認する:
|
|
224
|
+
|
|
225
|
+
- lazy lookup `t('.key')` … 実際の controller/view コンテキストでフルキーが決まる。
|
|
226
|
+
- 動的キー `t("views.#{type}.title")` … 静的に列挙できないキー。
|
|
227
|
+
- `_html` の表示崩れ・補間 `%{...}` … lookup 成功と表示の正しさは別。
|
|
228
|
+
|
|
229
|
+
確認したい場合は rspec(`docker compose up -d db` → `bundle exec rspec`)や主要画面で `translation missing` が
|
|
230
|
+
出ないか見る。i18n 参照パターンの確認例は `references/verification-per-prefix.md`。
|
|
231
|
+
|
|
232
|
+
> NOTE: regexp 追加(手順 7)後にスクリプトの regexp 引数と `local_first_key_regexp` がずれていないか、
|
|
233
|
+
> `bin/rails runner 'p CopyTunerClient.configuration.local_first_key?("<prefix>.foo")'` が `true`、隣接キー
|
|
234
|
+
> (`reviews.*` 等)が `false` になることを確認しておくとよい。
|
|
235
|
+
|
|
236
|
+
### 9. (初回のみ)CI の Export ステップを削除
|
|
237
|
+
|
|
238
|
+
CI で copy_tuner を export しているステップ(テストワークフロー内で `bin/rake copy_tuner:export` を走らせる類)
|
|
239
|
+
は、**テスト起動前にローカルキャッシュを温める保険**にすぎない。
|
|
240
|
+
このステップを削除すると、test 環境は initializer 起動時の `cache.download`(CopyTuner サーバから都度取得)
|
|
241
|
+
だけになり、**本番と同じ挙動**になる。未移行 prefix も引き続きサーバから解決できるので、移行途中に消しても安全。
|
|
242
|
+
|
|
243
|
+
> WARNING: `config.disable_test_translation = true` は**入れない**こと。入れると test で CopyTuner DL が
|
|
244
|
+
> 止まり、未移行 prefix が一斉に未訳化する。Export ステップ(保険)だけを消すのが正しい。
|
|
245
|
+
|
|
246
|
+
### 10. ドキュメントの中間状態を更新
|
|
247
|
+
|
|
248
|
+
i18n 方針ドキュメント(`doc/` 等)が「copy_tuner で管理/config/locales は使わない」のまま残ると、移行途中で
|
|
249
|
+
他の作業者や AI が「新規キーを copy_tuner と locales のどちらに足すか」を誤判断する。**移行中であることと、
|
|
250
|
+
現在ローカル化済みの prefix を明記する**。中間状態テンプレ文は `references/example-touchpoints.md` にある。
|
|
251
|
+
prefix を増やすたびに、列挙も更新する。
|
|
252
|
+
|
|
253
|
+
### 11. 残 prefix を報告
|
|
254
|
+
|
|
255
|
+
移行済み prefix・残 prefix の一覧と、現在の `local_first_key_regexp` を報告して 1 サイクル終了。
|
|
256
|
+
残 prefix があれば次サイクルでこのスキルを再実行する。全 prefix が移行済みになったら
|
|
257
|
+
`copy-tuner-to-locales-cleanup` スキルへ進む。
|
|
258
|
+
|
|
259
|
+
## 1 サイクル完了の目安
|
|
260
|
+
|
|
261
|
+
- 手順 6 のスクリプトが**移行漏れゼロを確認して正常終了**し、`--out`(`0010_` 以降)に対象 prefix が配置され、
|
|
262
|
+
`0000_original_*.yml` から該当サブツリーが削除されている(非表現値は `--out` 側に保持済み)。
|
|
263
|
+
- `local_first_key_regexp` に対象 prefix が `\A` アンカー付きで追加されている(手順 7)。
|
|
264
|
+
- 中間状態ドキュメントの「ローカル化済み prefix」が更新されている(手順 10)。
|
|
265
|
+
- (任意)rspec/画面で `translation missing` が出ないことをユーザー判断で確認(手順 8)。
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# 典型的な touchpoint(種別ごと)
|
|
2
|
+
|
|
3
|
+
copy_tuner(`copy_tuner_client` gem)を使う Rails アプリで、移行・撤去のときに触ることになる touchpoint を
|
|
4
|
+
種別ごとに整理したもの。**探索クエリを投げるとこういう種類の結果が返る**というサンプルとして読む。値やパスは
|
|
5
|
+
プロジェクトごとに違うので、これを暗記せず、各スキルの探索手順を必ず自分で走らせて発見すること
|
|
6
|
+
(migrate は手順 2、cleanup は手順 1)。
|
|
7
|
+
|
|
8
|
+
各 touchpoint に、どちらのスキルで触るかの印を付けた:
|
|
9
|
+
|
|
10
|
+
- **[migrate]** = `copy-tuner-to-locales-migrate-prefix`(このスキル)で触る。prefix 移行のたびに編集。
|
|
11
|
+
migrate の手順 2 で見つけ直すのはこの印の箇所だけ。
|
|
12
|
+
- **[cleanup]** = `copy-tuner-to-locales-cleanup`(全 prefix 完了後)で触る。gem・CI・deploy・docs・MCP 撤去。
|
|
13
|
+
撤去対象は cleanup の手順 1 で自前に grep し直す(migrate では棚卸ししない)。
|
|
14
|
+
|
|
15
|
+
## copy_tuner の典型的な touchpoint(種別ごと)
|
|
16
|
+
|
|
17
|
+
### gem 依存 — [cleanup]
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
# Gemfile
|
|
21
|
+
gem 'copy_tuner_client' # 全環境
|
|
22
|
+
gem 'copy_tuner_client-mcp', github: '<org>/copy_tuner_client-mcp',
|
|
23
|
+
require: false # development, test
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
> 段階移行の前提として、`copy_tuner_client` は **PR #110(local_first_key_regexp)入りバージョン**へ
|
|
27
|
+
> 上げておく必要がある(migrate スキル手順 1 で確認)。
|
|
28
|
+
|
|
29
|
+
### 初期化子 — [migrate](local_first_key_regexp を積み上げる中心)
|
|
30
|
+
|
|
31
|
+
`config/initializers/copy_tuner.rb`(パスはプロジェクトにより異なる):
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
CopyTunerClient.configure do |config|
|
|
35
|
+
config.api_key = Rails.application.credentials.fetch(:copytuner_api_key) { ENV.fetch('COPYTUNER_API_KEY', 'dummy') }
|
|
36
|
+
config.project_id = <プロジェクトの project_id>
|
|
37
|
+
config.host = '<copy_tuner サーバの host>'
|
|
38
|
+
config.html_escape = true
|
|
39
|
+
config.locales = [:ja]
|
|
40
|
+
config.ignored_keys = %w[]
|
|
41
|
+
# 移行のたびにここへ prefix を足していく:
|
|
42
|
+
# config.local_first_key_regexp = Regexp.union(/\Adevise\./, /\Aviews\./, ...)
|
|
43
|
+
end
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
→ `html_escape`(true 運用か)・運用ロケール(単一か複数か)という前提が分割・非表現値の判断に効くので、
|
|
47
|
+
実プロジェクトの initializer で確認する。initializer 全体の削除は [cleanup]。
|
|
48
|
+
|
|
49
|
+
> NOTE: `migrate_prefix.rb` は対象 locale を `I18n.available_locales`(既定。`--locales` で上書き可)から
|
|
50
|
+
> 取るので、運用ロケールが将来 `[:ja, :en]` 等に増えても引数なしで全ロケールを自動処理する(特定ロケール
|
|
51
|
+
> 決め打ちではない)。
|
|
52
|
+
|
|
53
|
+
### 既存 locales — [migrate](先頭固定リネーム → prefix サブツリーを後ろへ配置 → オリジナルから削除)
|
|
54
|
+
|
|
55
|
+
移行前の既存ファイル(初回サイクルの手順 2-1 で `0000_original_` へリネームする)。実ファイル名はプロジェクト
|
|
56
|
+
ごとに異なるので `ls config/locales` で確認して読み替える。典型的には次のような種類が並ぶ:
|
|
57
|
+
|
|
58
|
+
- Rails 標準(date/time/number/errors/helpers)の YAML
|
|
59
|
+
- devise 等の gem 由来 YAML
|
|
60
|
+
- アプリ固有の `activerecord.enums` / `activerecord.attributes` 等を持つ YAML
|
|
61
|
+
|
|
62
|
+
→ オリジナルを `0000_original_` で先頭固定し、移行分は `0010_` 以降に置く。重複キーはロード順の**後勝ちで
|
|
63
|
+
export 側が勝つ**(手作業マージ不要)。prefix を移行するたびにオリジナルから該当サブツリーを削除し、残存=
|
|
64
|
+
未移行 prefix の進捗マーカーにする(最終的にオリジナルが空=全移行完了)。
|
|
65
|
+
|
|
66
|
+
→ Rails 標準フォーマットの **配列**(`date.abbr_day_names` 等)・`date.order` の `:year` 等の**シンボル配列**・
|
|
67
|
+
`number.*.precision` 等の**非表現値**は copy_tuner で表現できず export に出てこないため、`date`/`number` を移行
|
|
68
|
+
する回では手順 6 のスクリプトがオリジナル抽出分をベースに export を上書き(`orig_sub.deep_merge(exp_sub)`)して
|
|
69
|
+
移行分(`0010_` 以降)の中へ**非表現値ごと取り込む**。別ファイルへの隔離は不要(詳細は
|
|
70
|
+
`references/export-and-split.md`)。
|
|
71
|
+
|
|
72
|
+
### CI — [migrate](Export ステップのみ初回で削除) / [cleanup](残り)
|
|
73
|
+
|
|
74
|
+
- **CI の翻訳 export ステップ**(テストワークフロー内で `bin/rake copy_tuner:export` を走らせる類)…
|
|
75
|
+
「翻訳 DL 失敗でテストがコケないように」の保険。**[migrate] の初回で削除**(test が本番同等の
|
|
76
|
+
`cache.download` 挙動になる)。`disable_test_translation` は入れない。
|
|
77
|
+
- **copy_tuner 専用の deploy ワークフロー**(main push で翻訳をデプロイする専用ファイル)…
|
|
78
|
+
**[cleanup] で丸ごと削除**。
|
|
79
|
+
- **AI エージェント用ワークフローの `mcp__copy-tuner__*` allowedTools 許可** … **[cleanup] で削除**。
|
|
80
|
+
|
|
81
|
+
### deploy / 起動スクリプト — [cleanup]
|
|
82
|
+
|
|
83
|
+
- **deploy フック** … production 起動時に `bundle exec rake copy_tuner:deploy` を実行するブロック。削除。
|
|
84
|
+
- **コンテナ起動スクリプト** … 起動時に `rake copy_tuner:export` を走らせるフォールバック。**gem 撤去後は
|
|
85
|
+
このタスク自体が消えて起動が `Don't know how to build task` で落ちる**ため、必ず削除する。取りこぼし注意。
|
|
86
|
+
|
|
87
|
+
### 環境設定 — [cleanup] で確認
|
|
88
|
+
|
|
89
|
+
`config/environments/production.rb` の `config.i18n.fallbacks = true` 等。標準バックエンドでも有効なので確認のみ。
|
|
90
|
+
|
|
91
|
+
### ドキュメント / スキル / MCP — [migrate](中間状態更新) / [cleanup](最終化・撤去)
|
|
92
|
+
|
|
93
|
+
- **i18n 方針ドキュメント**(`CLAUDE.md`・`doc/` 配下等)… 「copy_tuner サーバで i18n データを管理 /
|
|
94
|
+
config/locales 配下は利用しない / 新規キー登録は基本禁止」等の記述。**[migrate] で中間状態に更新**、
|
|
95
|
+
**[cleanup] で最終化**。上記を参照している他のドキュメント(`CLAUDE.md` 等)も連動。
|
|
96
|
+
- **copy_tuner MCP 操作スキル**(`.claude/skills/` 配下)… **[cleanup] で無効化/削除**。
|
|
97
|
+
- **補助ドキュメント** … 「多言語対応: copy_tuner サーバで i18n データを管理」のような記述を持つコマンド定義等。
|
|
98
|
+
**[cleanup] で修正**。
|
|
99
|
+
- **`README.md`** … CopyTuner プロジェクトへのリンク。**[cleanup] で削除/修正**。
|
|
100
|
+
- **`.mcp.json`** … copy-tuner MCP server 接続設定。**[cleanup] で削除**。
|
|
101
|
+
|
|
102
|
+
## 規模感
|
|
103
|
+
|
|
104
|
+
copy_tuner 側のキー数・export YAML の行数はプロジェクト次第だが、export YAML のトップには Rails i18n 慣習どおりの
|
|
105
|
+
セクションが並ぶ: `activemodel.attributes` / `activerecord.{attributes,enums,models,errors}` / `views` / `text` /
|
|
106
|
+
`helpers` / `date`/`time`/`datetime`/`number` / `devise` / `good_job` / `ice_cube` /
|
|
107
|
+
`restrict_dependent_destroy` 等。これらのトップセクションが prefix 移行の基本粒度。`views` が最大になりやすいので
|
|
108
|
+
最後に回す。
|
|
109
|
+
|
|
110
|
+
## i18n 方針ドキュメント中間状態テンプレ([migrate] 手順 10 で使う)
|
|
111
|
+
|
|
112
|
+
移行中はこのような記述に置き換える。`<列挙>` は現在 `local_first_key_regexp` にマッチしている prefix に
|
|
113
|
+
更新する(prefix を増やすたびに更新)。
|
|
114
|
+
|
|
115
|
+
```markdown
|
|
116
|
+
### 国際化(i18n)
|
|
117
|
+
|
|
118
|
+
- **copy_tuner から config/locales へ段階移行中**
|
|
119
|
+
- 以下の prefix は config/locales 管理へ移行済み(`local_first_key_regexp` にマッチ): `<列挙: devise, ice_cube, views, ...>`
|
|
120
|
+
- 上記以外の prefix はまだ copy_tuner サーバで管理
|
|
121
|
+
- **新規キーの追加先**: 移行済み prefix のキーは config/locales へ。未移行 prefix のキーは従来どおり copy_tuner へ
|
|
122
|
+
- 複数形化対応は不要(日本語環境)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> [cleanup] で全 prefix 完了後、この中間記述は「config/locales 管理。copy_tuner 廃止。新規キーは
|
|
126
|
+
> config/locales へ。複数形化不要」に最終化する(モデル名・カラム名の例外規定も撤廃)。
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# export と prefix サブツリーの抜き出し・YAML 分割
|
|
2
|
+
|
|
3
|
+
SKILL.md 手順 3・6 の詳細。
|
|
4
|
+
|
|
5
|
+
## rake copy_tuner:export の挙動
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bundle exec rake copy_tuner:export[出力先パス]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
- 引数を省略するとデフォルトで `config/locales/copy_tuner.yml` に書き出す。**段階移行では全件を一時ファイルへ
|
|
12
|
+
出して俯瞰・抜き出しの元データにする**ため、`tmp/copy_tuner_all.yml` のような捨て場を明示指定する。
|
|
13
|
+
- 内部で `CopyTunerClient.cache.sync` を呼び、copy_tuner サーバから最新 blurb を取得してから書き出す。
|
|
14
|
+
ローカルのポーラーキャッシュ任せにせず必ずこのタスクを使うのは、同期済み・全件であることを保証するため。
|
|
15
|
+
- blurb が一件もキャッシュできないと `No blurbs have been cached.` で失敗する。その場合は API key
|
|
16
|
+
(credentials または `COPYTUNER_API_KEY`)と project_id の設定、ネットワーク到達性を確認する。
|
|
17
|
+
- 出力は単一の YAML で、トップに copy_tuner に登録された全ロケールのキー(`ja:`、複数運用なら `en:` 等も)が
|
|
18
|
+
並び、その下に blurb のドット区切りキーがネストした Hash に展開された形になる。
|
|
19
|
+
|
|
20
|
+
## 出力 YAML の構造(典型)
|
|
21
|
+
|
|
22
|
+
トップレベルロケール(複数運用なら `ja:` / `en:` …)の下に、Rails の i18n 慣習どおりのセクションがフラットに
|
|
23
|
+
並ぶ。実際のプロジェクトではおおむね次のようなセクションが現れる:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
ja: # 複数ロケール運用なら en: 等も同じ構造で並ぶ
|
|
27
|
+
activemodel:
|
|
28
|
+
attributes: # Form オブジェクトの属性名
|
|
29
|
+
activerecord:
|
|
30
|
+
attributes: # モデル属性名(CSV ヘッダ・フォームラベル等)
|
|
31
|
+
enums: # enum 値の表示名
|
|
32
|
+
models: # モデルの human 名
|
|
33
|
+
errors: # カスタムバリデーションメッセージ
|
|
34
|
+
views: # 画面テキスト・ヘルプ文
|
|
35
|
+
text: # 汎用ボタンテキスト等
|
|
36
|
+
helpers: # submit ラベル等
|
|
37
|
+
date: / time: / datetime: / number: # Rails 標準フォーマット
|
|
38
|
+
devise: # gem 由来
|
|
39
|
+
good_job: / ice_cube: / restrict_dependent_destroy: # gem 由来
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
このトップセクションの単位が、SKILL.md 手順 4 の「対象 prefix」の基本粒度になる。
|
|
43
|
+
|
|
44
|
+
## 対象 prefix のサブツリーだけを抜き出す(スクリプトが担う)
|
|
45
|
+
|
|
46
|
+
段階移行では**今回の prefix のサブツリーだけ**を config/locales へ持ち込む(全件は持ち込まない)。この抽出・
|
|
47
|
+
配置・検証・削除は SKILL.md 手順 6 の `scripts/migrate_prefix.rb` が決定論的に行う。スクリプトの内部処理:
|
|
48
|
+
|
|
49
|
+
- 全件 export YAML(`tmp/copy_tuner_all.yml`)から対象 prefix(例 `views`)以下を、対象 locale(`--locales`/
|
|
50
|
+
既定は `I18n.available_locales`)すべてのロケールキー(`ja:`、複数運用なら `en:` 等)を保ったまま切り出す。
|
|
51
|
+
他の prefix(まだ移行しないもの)は持ち込まない(引き続き CopyTuner から引かれる)。
|
|
52
|
+
- 抜き出した leaf キーが手順 7 で `local_first_key_regexp` に足す prefix(`--regexp`/既定 `/\A<prefix>\./`)と
|
|
53
|
+
**一致しているか**を静的ガードで自動確認する(regexp がマッチするのにローカルに無い=未訳を防ぐ)。
|
|
54
|
+
|
|
55
|
+
## 分割の方針(配置先ファイル)
|
|
56
|
+
|
|
57
|
+
スクリプトの `--out` は、**オリジナル(`0000_original_*.yml`)より後にロードされる採番**(`0010_` 以降)の
|
|
58
|
+
ファイルにする。SKILL.md 手順 2-1 で既存 locales を `0000_original_` に固定済みなので、移行分を後ろに置けば
|
|
59
|
+
Rails i18n の後勝ちで**重複キーは自動的に export 側が勝つ**(手作業マージ不要)。
|
|
60
|
+
|
|
61
|
+
分割の目安(1 prefix = 1 ファイルにすると、どの prefix を移行済みか/regexp と config/locales の対応が追いやすい):
|
|
62
|
+
|
|
63
|
+
| ファイル例 | 入れるセクション |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `0000_original_*.yml`(既存・先頭固定) | 未移行 prefix の残り(移行のたびに該当 prefix を削除していく) |
|
|
66
|
+
| `0020_activerecord.yml` | `activerecord.attributes` / `activerecord.models` / `activerecord.errors` |
|
|
67
|
+
| `0030_activemodel.yml` | `activemodel.attributes` / `activemodel.errors` |
|
|
68
|
+
| `0040_views.yml` | `views` / `text` |
|
|
69
|
+
| `0050_gems.yml` | good_job / ice_cube / restrict_dependent_destroy / devise 等 |
|
|
70
|
+
|
|
71
|
+
> 採番は目安。ポイントは **`0000_original_`(先頭)< 移行分 `0010_` 以降** のロード順を保つこと。
|
|
72
|
+
> これにより重複キーは **export 側を正とする**が構造的に保証される(次節)。非表現値(date/number の配列・
|
|
73
|
+
> シンボル・数値)は別ファイルに隔離せず、スクリプトが移行分(`0010_` 以降)の中へ取り込む(後述)。
|
|
74
|
+
|
|
75
|
+
## 既存 locales との重複は後勝ちで解決し、オリジナルから削除する
|
|
76
|
+
|
|
77
|
+
抜き出したサブツリーに、すでにオリジナル(`0000_original_*.yml`)に存在するキー(Rails 標準・devise・
|
|
78
|
+
アプリ固有 enum 等)が含まれることがある。**手作業でのマージはしない。** スクリプトとロード順で解決する:
|
|
79
|
+
|
|
80
|
+
- スクリプトは `orig_sub.deep_merge(exp_sub)`(オリジナル抽出分をベースに export で上書き)で `--out` を作る。
|
|
81
|
+
葉が両方にあれば export が勝ち、**「export を正とする」を満たす**。さらに `0000_` 先頭・`0010_` 後ロードの
|
|
82
|
+
Rails 後勝ちでも二重に保証される。
|
|
83
|
+
- 配置・移行漏れ検証を通った後、スクリプトが**移行した prefix のサブツリーをオリジナルから削除する**
|
|
84
|
+
(空親も刈る)。残存内容が「未移行 prefix」を表す進捗マーカーになり、重複定義も消えて YAML がクリーンに保たれる。
|
|
85
|
+
|
|
86
|
+
## copy_tuner で表現できない値(非表現値)の引き継ぎ
|
|
87
|
+
|
|
88
|
+
copy_tuner は flat な文字列 blurb しか持てないため、次の値は export に出てこない/文字列化されて壊れる:
|
|
89
|
+
|
|
90
|
+
- **配列**: `date.abbr_day_names` / `day_names` / `month_names` / `abbr_month_names` 等
|
|
91
|
+
- **シンボル配列**: `date.order`(`:year` / `:month` / `:day`)等
|
|
92
|
+
- **数値・真偽値**: `number.*.precision`(整数)/ `significant` / `strip_insignificant_zeros`(真偽値)等
|
|
93
|
+
- **ハッシュ値**: 上記のように構造を持つ Rails 標準フォーマット群
|
|
94
|
+
|
|
95
|
+
これらは基本 export に出てこず**オリジナルにしか無い**が、**壊れた形(文字列化された値、過去に管理画面で手動
|
|
96
|
+
登録された値、将来の gem の型変換結果)で export に出てくる可能性**もある。スクリプトは 3 段の deep merge で
|
|
97
|
+
これを守る:
|
|
98
|
+
|
|
99
|
+
1. `orig_sub` をベースに
|
|
100
|
+
2. export を上書き(String blurb は export 勝ち)
|
|
101
|
+
3. 最後に**オリジナル由来の非表現値(非 String leaf)だけ**を再適用(`select_non_blurb(orig_sub)`)
|
|
102
|
+
|
|
103
|
+
これにより、export に壊れた非表現値が出ても **3 段目で orig の正値が置換勝ちする**(deep merge は配列・スカラを
|
|
104
|
+
右辺で置換するので、最後に来た orig 値が export の壊れた値を上書きする)。**非表現値は orig 値で `--out` に残る**。
|
|
105
|
+
別ファイル(旧 `0005_rails_non_blurb.yml`)への隔離は**不要**。
|
|
106
|
+
|
|
107
|
+
> 原則の住み分け: 「重複キーは export を正とする」は **copy_tuner で表現可能な String blurb にのみ**成り立つ。
|
|
108
|
+
> 非表現値はそもそも copy_tuner に正しく存在しえない(gem の `store_item` が `respond_to?(:to_str)` で非文字列を
|
|
109
|
+
> 弾く)ので、orig を勝たせるのが常に正しい。同じ `date` prefix 内で `date.formats`(文字列・export 勝ち)と
|
|
110
|
+
> `date.order`(シンボル配列・orig 勝ち)が排他的に住み分く。2 原則は衝突しない。
|
|
111
|
+
|
|
112
|
+
> なぜ隔離が要らないか: 隔離方式は「export 由来ファイルに非表現値を混ぜると壊れる」ことを避ける狙いだったが、
|
|
113
|
+
> スクリプトは 3 段マージ(orig ベース → export 上書き → 非表現値の再適用)で非表現値の喪失・上書きを構造的に
|
|
114
|
+
> 防ぎ、`--out` 単一ファイルに収める。削除も「漏れゼロを実 lookup で確認してから」スクリプトが行うので、
|
|
115
|
+
> 非表現値を巻き添えで失う事故(prefix を丸ごと消す手作業ミス)も起きない。
|
|
116
|
+
|
|
117
|
+
> 参考: gem 側の型変換は [copy-tuner-ruby-client#104](https://github.com/SonicGarden/copy-tuner-ruby-client/pull/104)
|
|
118
|
+
> で `*.precision` → integer、`*.significant` → boolean 等が補われる。ただし**配列・シンボルは対象外**。いずれに
|
|
119
|
+
> せよ 3 段目の非表現値再適用で orig 値が勝つため、coerce された値・壊れた値どちらが export に出ても安全。
|
|
120
|
+
|
|
121
|
+
## html_escape 由来の値の扱い
|
|
122
|
+
|
|
123
|
+
copy_tuner を `html_escape = true` で運用していた場合、export された値には HTML エスケープ前提の文字列や
|
|
124
|
+
`*_html` キー慣習が含まれることがある。Rails 標準の i18n も `*_html` サフィックスのキーは自動で
|
|
125
|
+
`html_safe` 扱いにするため、基本はそのまま移せる。ただし SKILL.md 手順 5 の `detect_html_incompatible_keys`
|
|
126
|
+
で警告が出たキーは、移行前に copy_tuner 側で整理しておくこと(そのまま持ち込むと表示が壊れる)。
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# local_first_key_regexp の使い方
|
|
2
|
+
|
|
3
|
+
SKILL.md 手順 7 の詳細。prefix 単位移行の核心となる gem オプション。
|
|
4
|
+
|
|
5
|
+
## 何をするオプションか
|
|
6
|
+
|
|
7
|
+
[copy-tuner-ruby-client #110](https://github.com/SonicGarden/copy-tuner-ruby-client/pull/110) で
|
|
8
|
+
`Configuration#local_first_key_regexp` が追加された。`I18nBackend#lookup` は次のように動く:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
# locale を除いたキー(例: "views.foo.bar")が regexp にマッチしたら…
|
|
12
|
+
if local_first_key?(key_without_locale)
|
|
13
|
+
return super # ← I18n::Backend::Simple に委譲。CopyTuner キャッシュもアップロードキューも触らない
|
|
14
|
+
end
|
|
15
|
+
# マッチしなければ従来どおり CopyTuner キャッシュ優先 → 無ければ super
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
判定は `key_without_locale.to_s.match?(local_first_key_regexp)` の単純マッチ。
|
|
19
|
+
|
|
20
|
+
## 完全分離の意味
|
|
21
|
+
|
|
22
|
+
マッチキーは **CopyTuner を一切参照しない**。つまり:
|
|
23
|
+
|
|
24
|
+
- ローカル YAML に値があればそれを返す。
|
|
25
|
+
- ローカル YAML に**無ければ即 `nil`(未訳)**。CopyTuner へフォールバックしない。
|
|
26
|
+
- 空キーのアップロードキュー投入もしない(`Cache#[]=` の単一関門で抑止)。
|
|
27
|
+
- CopyRay のオーバーレイマーカー(`<!--COPYRAY key-->`)も注入されない(編集できないキーを編集可能と誤認
|
|
28
|
+
させないため)。
|
|
29
|
+
|
|
30
|
+
この「無ければ未訳」の挙動こそが、**移行漏れ(ローカルへ書き忘れたキー)を未訳として顕在化させる**仕組み。
|
|
31
|
+
だから移行のたびに `translation missing` チェック(SKILL.md 手順 8)が効く。
|
|
32
|
+
|
|
33
|
+
## regexp は単一・配列非対応
|
|
34
|
+
|
|
35
|
+
`local_first_key_regexp` は単一の `Regexp` を取る(`attr_accessor`、デフォルト `nil`)。**配列は渡せない**。
|
|
36
|
+
複数 prefix を移行済みにするには **1 本の正規表現に積み上げる**。`Regexp.union` を使うのが安全:
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
config.local_first_key_regexp = Regexp.union(
|
|
40
|
+
/\Adevise\./,
|
|
41
|
+
/\Aice_cube\./,
|
|
42
|
+
/\Arestrict_dependent_destroy\./,
|
|
43
|
+
/\Aviews\./,
|
|
44
|
+
)
|
|
45
|
+
# => /(?-mix:\Adevise\.)|(?-mix:\Aice_cube\.)|.../ 相当
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`Regexp.union` はメタ文字のエスケープを自動でやり、要素を OR でつなぐので、prefix を 1 行ずつ足すだけで済む。
|
|
49
|
+
手書きの `/\A(devise|ice_cube|...)\./` でも等価だが、union のほうが追記時のミスが少ない。
|
|
50
|
+
|
|
51
|
+
## `\A` アンカー必須
|
|
52
|
+
|
|
53
|
+
各 prefix は **`\A` で先頭アンカー**する。キーは locale 除去後なので `\A` 起点でよい。
|
|
54
|
+
|
|
55
|
+
- `\A` 無しの `/views\./` は `reviews.foo` の `views.` 部分にもマッチしてしまう(部分マッチ事故)。
|
|
56
|
+
- `\Aviews\.` なら `views.` で始まるキーだけにマッチする。
|
|
57
|
+
- `views` 配下を更に刻むなら `\Aviews\.users\.` のように 2 階層目までアンカーできる。
|
|
58
|
+
|
|
59
|
+
ドット `.` は正規表現のメタ文字なので、prefix 区切りのドットは `\.` とエスケープする
|
|
60
|
+
(`/\Aviews\./`。`Regexp.union` に文字列を渡す場合は自動エスケープされるが、Regexp リテラルを渡すときは自分で
|
|
61
|
+
書く)。
|
|
62
|
+
|
|
63
|
+
## deprecated な exclude_key_regexp との違い
|
|
64
|
+
|
|
65
|
+
| | `local_first_key_regexp` | `exclude_key_regexp`(非推奨) |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| 対象キー | locale を**除いた**キー(`views.foo`) | locale を**含む**キー(`ja.views.foo`) |
|
|
68
|
+
| 作用タイミング | lookup(読み込み)時 | upload(送信)時 |
|
|
69
|
+
| 効果 | ローカル YAML を優先(完全分離) | サーバへのアップロードを抑止するだけ |
|
|
70
|
+
|
|
71
|
+
`exclude_key_regexp` は PR #110 で非推奨化された(設定すると `ActiveSupport::Deprecation` 警告が出る)。
|
|
72
|
+
移行では使わない。もし既存設定に `exclude_key_regexp` があれば、cleanup スキルで gem ごと撤去される。
|