copy_tuner_client 1.2.4 → 1.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ab3f862812c6f70f5157abe63b5d7cc860037be7b429173b33f5e845fca8d5f
4
- data.tar.gz: f14a689fb3bc5e39de2cbe7489b81c5371f502feec84cb3367de3d57ddf2b673
3
+ metadata.gz: d298d7f59a4cacd30c925e2a0af2b6026fbd3610d4564fae70e5b6efbad4ad0c
4
+ data.tar.gz: 0f7e09019505a1b49353550b696a2f4a0a4a40eaf74573e4a4e916ec547bd1e9
5
5
  SHA512:
6
- metadata.gz: ac8dd0b44dc790805421993444bf09e8b28c63a7532796367acfc90e366c7b806e412f6e04d8c451f5c204ebd283e23d15bd9b32ec8912bbbc820e994d184fd4
7
- data.tar.gz: bcce2f96d4b748280edba1bf962a7e19f93a42e9af74d37a6b10c914e7e98408c1dcc856e771763c8dededa4aa379828d408da133167dad4c512e52c8a6503b8
6
+ metadata.gz: 934b99a1624d8dd517c9f2df68c37ffb667128beca73222db458b5f973534398eda88f01c6550c48219e54205fb14b6e47d9731f9556ec0c55d06ce5b47b3729
7
+ data.tar.gz: 11e6f16e6792603ee6d5c74f4888f293895cf483d10f88d57298bc80bd54a05cb50da5dcdba2c9ade055bf6d57afe66a398b355de806a87a0528dea9e19efaae
data/README.md CHANGED
@@ -53,6 +53,16 @@ CopyTuner で一元管理している翻訳を、`views.*` のような単位で
53
53
  - ローカル YAML にも存在しない場合は未訳(`nil` / MissingTranslation)となります。CopyTuner へのフォールバックや新規キーのアップロードは行いません。これにより移行漏れを未訳として検知できます。
54
54
  - マッチしたキーには、ビューヘルパー(`t` / `translate`)および SimpleForm のラベルで CopyRay オーバーレイマーカー(`<!--COPYRAY key-->`)を注入しません。これらのキーは CopyTuner 上で編集できないため、編集可能だと誤認させないためです。
55
55
 
56
+ ### Rails 標準の数値フォーマットキーは常にローカル優先(組み込み)
57
+
58
+ `local_first_key_regexp` の設定有無にかかわらず、以下の Rails 標準キーは**常にローカル YAML 優先**になります(CopyTuner をバイパス)。
59
+
60
+ - `number.format` / `number.currency.format` / `number.percentage.format` / `number.human.format`(およびその配下)
61
+
62
+ これらは `precision`(整数)や `significant` / `strip_insignificant_zeros`(真偽値)といった非文字列値を含みます。CopyTuner は文字列値しか保持できないため、経由するとこれらが欠落し、`number_to_currency` などが意図しない表示(小数桁数や記号の崩れ)になります。これを防ぐため gem 側で固定的にローカル優先にしています。
63
+
64
+ アプリ独自の `number.*` キー(例 `number.gift_amount`)は対象外で、従来どおり CopyTuner で管理できます。
65
+
56
66
  `exclude_key_regexp` との違い:
57
67
 
58
68
  | オプション | 対象 | 作用するタイミング |
@@ -56,8 +56,8 @@ module CopyTunerClient
56
56
 
57
57
  # NOTE: config/locales以下のファイルに除外キーが残っていた場合の対応
58
58
  key_without_locale = key.split('.')[1..].join('.')
59
- # NOTE: local_first_key_regexp にマッチするキーは copy_tuner と完全分離するためアップロードしない
60
- return if @local_first_key_regexp && key_without_locale.match?(@local_first_key_regexp)
59
+ # NOTE: local_first キー(組み込みの Rails number.*.format + ユーザー設定)は copy_tuner と完全分離するためアップロードしない
60
+ return if local_first_key?(key_without_locale)
61
61
 
62
62
  if @ignored_keys.include?(key_without_locale)
63
63
  @ignored_key_handler.call(IgnoredKey.new("Ignored key: #{key_without_locale}"))
@@ -165,6 +165,14 @@ module CopyTunerClient
165
165
 
166
166
  attr_reader :client, :logger
167
167
 
168
+ # NOTE: 組み込みの Rails number.*.format キーは lookup 経路(Configuration#local_first_key?)と
169
+ # アップロード抑止経路(ここ)で同じ判定を共有する。判定本体は Configuration に集約し付け忘れの穴を防ぐ。
170
+ def local_first_key?(key_without_locale)
171
+ return true if Configuration.builtin_local_first_key?(key_without_locale)
172
+
173
+ @local_first_key_regexp && key_without_locale.match?(@local_first_key_regexp)
174
+ end
175
+
168
176
  def with_queued_changes
169
177
  changes_to_push = nil
170
178
 
@@ -21,6 +21,21 @@ module CopyTunerClient
21
21
  ca_file exclude_key_regexp local_first_key_regexp s3_host locales ignored_keys ignored_key_handler
22
22
  download_cache_dir].freeze
23
23
 
24
+ # NOTE: Rails 標準ロケールで非文字列値(precision: Integer, significant: Boolean,
25
+ # strip_insignificant_zeros: Boolean)を含むのは number.*.format 配下のみ。store_item が文字列しか
26
+ # 保持できず lookup_in_tree_cache が tree cache をローカル YAML より優先するため、CopyTuner 経由だと
27
+ # precision 等が欠落し number_to_currency 等が壊れる。これらの Rails 標準 format キーだけを常にローカル
28
+ # 優先にする(number 全体ではなく、アプリ独自の number.* キーは対象外)。末尾 (\.|\z) で
29
+ # number.currency.format(ハッシュ lookup)と number.currency.format.precision(葉キー)の両方に対応する。
30
+ BUILTIN_LOCAL_FIRST_KEY_REGEXP =
31
+ /\Anumber\.(format|currency\.format|percentage\.format|human\.format)(\.|\z)/
32
+
33
+ # lookup 経路(Configuration#local_first_key?)と upload 抑止経路(Cache#[]=)で同じ組み込み判定を
34
+ # 共有する。判定を 1 箇所に集約することで number 以外を足す際の同期漏れを防ぐ。
35
+ def self.builtin_local_first_key?(key_without_locale)
36
+ key_without_locale.to_s.match?(BUILTIN_LOCAL_FIRST_KEY_REGEXP)
37
+ end
38
+
24
39
  # @return [String] The API key for your project, found on the project edit form.
25
40
  attr_reader :api_key
26
41
 
@@ -363,9 +378,13 @@ module CopyTunerClient
363
378
  # @param key_without_locale [String, Symbol, nil] locale prefix を除いたキー(例: "views.foo.bar")
364
379
  # @return [Boolean]
365
380
  def local_first_key?(key_without_locale)
366
- return false if local_first_key_regexp.nil? || key_without_locale.nil?
381
+ return false if key_without_locale.nil?
382
+
383
+ normalized = key_without_locale.to_s
384
+ return true if self.class.builtin_local_first_key?(normalized)
385
+ return false if local_first_key_regexp.nil?
367
386
 
368
- key_without_locale.to_s.match?(local_first_key_regexp)
387
+ normalized.match?(local_first_key_regexp)
369
388
  end
370
389
 
371
390
  private
@@ -1,6 +1,6 @@
1
1
  module CopyTunerClient
2
2
  # Client version
3
- VERSION = '1.2.4'.freeze
3
+ VERSION = '1.3.0'.freeze
4
4
 
5
5
  # API version being used to communicate with the server
6
6
  API_VERSION = '2.0'.freeze
@@ -20,6 +20,11 @@ license: MIT
20
20
  | マッチする | config/locales(copy_tuner と完全分離) | `config/locales/*.yml` を Read / Edit |
21
21
  | マッチしない・未設定 | copy_tuner | MCP ツール(下記) |
22
22
 
23
+ **例外(gem 組み込み・設定不要で常に config/locales 管理):** Rails 標準の `number.format` /
24
+ `number.currency.format` / `number.percentage.format` / `number.human.format`(およびその配下)。
25
+ `precision` 等の非文字列値を含み copy_tuner では正しく扱えないため、gem が常にバイパスする。
26
+ これらは `config/locales/*.yml` を見る・編集すること(アプリ独自の `number.gift_amount` 等は対象外で通常どおり copy_tuner)。
27
+
23
28
  **config/locales 管理キーの落とし穴:**
24
29
  - copy_tuner には存在しないので、MCP ツールで探しても見つからない。`config/locales` を見ること。
25
30
  - copy_tuner に登録しても lookup でバイパスされ無効。必ず `.yml` 側に書く。
@@ -55,6 +55,18 @@ describe 'CopyTunerClient::Cache' do
55
55
  expect(cache.queued.keys).to match_array(%w[ja.views.foo ja.messages.bar])
56
56
  end
57
57
 
58
+ it 'Rails標準の number.*.format キーは設定なしでもアップロードしないこと' do
59
+ cache = build_cache(local_first_key_regexp: nil)
60
+ cache['ja.number.currency.format.unit'] = '$'
61
+ cache['ja.number.gift_amount'] = 'app key'
62
+ cache['ja.messages.bar'] = 'copy tuner value'
63
+
64
+ cache.download
65
+
66
+ # number.*.format のみ抑止。アプリ独自 number キーと通常キーは従来どおりアップロード
67
+ expect(cache.queued.keys).to match_array(%w[ja.number.gift_amount ja.messages.bar])
68
+ end
69
+
58
70
  it '変更がない場合はアップロードしないこと' do
59
71
  cache = build_cache
60
72
  cache.flush
@@ -217,6 +217,40 @@ describe CopyTunerClient::Configuration do
217
217
  expect(config.local_first_key?(:'views.foo')).to eq true
218
218
  end
219
219
  end
220
+
221
+ # NOTE: Rails 標準の number.*.format 配下は precision 等の非文字列値を含み CopyTuner 経由だと壊れるため、
222
+ # ユーザー設定の有無によらず常にローカル優先(組み込み判定)になる
223
+ context 'with built-in Rails number format keys' do
224
+ it 'returns true for built-in number format keys even when local_first_key_regexp is nil' do
225
+ expect(config.local_first_key?('number.format')).to eq true
226
+ expect(config.local_first_key?('number.currency.format')).to eq true
227
+ expect(config.local_first_key?('number.currency.format.precision')).to eq true
228
+ expect(config.local_first_key?('number.percentage.format')).to eq true
229
+ expect(config.local_first_key?('number.human.format.significant')).to eq true
230
+ end
231
+
232
+ it 'returns false for app-defined number keys (not Rails format subtrees)' do
233
+ expect(config.local_first_key?('number.gift_amount')).to eq false
234
+ expect(config.local_first_key?('number.my_currency.unit')).to eq false
235
+ end
236
+
237
+ it 'returns false for string-only number subtrees and non-number keys' do
238
+ expect(config.local_first_key?('number.human.storage_units.units.byte.one')).to eq false
239
+ expect(config.local_first_key?('date.formats.default')).to eq false
240
+ expect(config.local_first_key?('time.formats.short')).to eq false
241
+ expect(config.local_first_key?('datetime.distance_in_words.x')).to eq false
242
+ expect(config.local_first_key?('views.foo')).to eq false
243
+ expect(config.local_first_key?('numbers.foo')).to eq false
244
+ end
245
+
246
+ it 'keeps protecting built-in keys without breaking a user-set regexp' do
247
+ config.local_first_key_regexp = /\Aviews\./
248
+
249
+ expect(config.local_first_key?('number.currency.format')).to eq true
250
+ expect(config.local_first_key?('views.foo')).to eq true
251
+ expect(config.local_first_key?('models.foo')).to eq false
252
+ end
253
+ end
220
254
  end
221
255
 
222
256
  describe '#exclude_key_regexp= (deprecated)' do
@@ -445,7 +445,7 @@ describe 'CopyTunerClient::I18nBackend' do
445
445
  end
446
446
  end
447
447
 
448
- describe 'local_first_key_regexp(ローカル優先キー)' do
448
+ describe 'local_first_key_regexp(ローカル優先キー)' do # rubocop:disable Metrics/BlockLength
449
449
  after { CopyTunerClient.configuration.local_first_key_regexp = nil }
450
450
 
451
451
  # ローカル config/locales 相当のデータを I18n::Backend::Simple 側だけに格納する。
@@ -468,6 +468,24 @@ describe 'CopyTunerClient::I18nBackend' do
468
468
 
469
469
  expect(subject.translate('ja', 'views.foo')).to eq('copy tuner value')
470
470
  end
471
+
472
+ # NOTE: number.*.format は precision 等の非文字列値が store_item で落ちるため、
473
+ # tree cache を優先するとローカル YAML の正しい format が壊れる。組み込み判定で常にローカル優先にする。
474
+ it 'number.*.format は cache に値があってもローカル YAML を優先すること' do
475
+ CopyTunerClient.configuration.local_first_key_regexp = nil
476
+ cache['ja.number.currency.format.unit'] = '$'
477
+ store_local(subject, :ja, number: { currency: { format: { unit: '円' } } })
478
+
479
+ expect(subject.translate('ja', 'number.currency.format')).to eq(unit: '円')
480
+ end
481
+
482
+ it 'アプリ独自の number キーは従来どおり copy_tuner を優先すること' do
483
+ CopyTunerClient.configuration.local_first_key_regexp = nil
484
+ cache['ja.number.gift_amount'] = 'copy tuner value'
485
+ store_local(subject, :ja, number: { gift_amount: 'local value' })
486
+
487
+ expect(subject.translate('ja', 'number.gift_amount')).to eq('copy tuner value')
488
+ end
471
489
  end
472
490
 
473
491
  context 'local_first_key_regexp = /\Aviews\./ のとき' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: copy_tuner_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SonicGarden