copy_tuner_client 1.2.2 → 1.2.3

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: 4c37179f53ed11fd69930c2b4ff36d6597d0e83ab45e749c5711b7bef254ff2d
4
- data.tar.gz: b67cd75f1997c995ba84bee721267b2ceeb1df236907d71c982b5b2058702dc1
3
+ metadata.gz: f671e8161b117c8d8d46b5ae56810ccd0e2fc88dbe9d35ab2175d303c89df11c
4
+ data.tar.gz: 5cf906cd134cda913900d2e15e970a094b23f01a03f9914c746b0e2da3ee6c26
5
5
  SHA512:
6
- metadata.gz: b17a757326468fa69d31d6e86ea684c9f7df6b76b6792429da5cd5d7db0cb0e15392ebdd9f20f66952ebdb7f8770ff3baa636a77f7742134a4053032a2d6e230
7
- data.tar.gz: a2df2195d3096ff198893298f968c453564f479a98393f6bfe93f133fcbc414fec7bd004142e6d9f680df28dbebb79535813f79fc273c1b0448906784edfd4d2
6
+ metadata.gz: 84f11e2d259e496f0638b3b8914cc3f88ceda67c6ae1e497f37192fd55347b0f8948abe115c5b91d33ee8feb3acdfb7994fd0af0b4a3118a64ee763dfc458b89
7
+ data.tar.gz: 97f296346a8eff7bb3b09ae4b6de6757973ec859e771492962031440626df13548dc25705ebcb355a14e94038444d1223b325c49caff3a1d87f3ec034bde1561
data/CLAUDE.md CHANGED
@@ -18,6 +18,11 @@ CopyTuner の Ruby クライアント gem。Rails アプリの I18n を CopyTune
18
18
  - Rack middleware `RequestSync` / `CopyrayMiddleware` — 開発環境でのリクエスト毎同期とオーバーレイ
19
19
  Rails 統合は engine.rb のイニシャライザ経由(ヘルパー/SimpleForm フック、アセット precompile)。
20
20
 
21
+ ## 開発スタイル
22
+ - **RED/TDD で進める**: 実装前に必ず失敗するテストを書き、テストが RED になることを確認してから実装する
23
+ - 新機能・バグ修正ともに「テスト追加 → RED 確認 → 実装 → GREEN」のサイクルを守る
24
+ - テストを書かずに実装を先行させない
25
+
21
26
  ## Gotchas
22
27
  - **フロントエンドは `src/*.ts` を編集する。`app/assets/*` は Vite のビルド成果物なので直接編集しない**
23
28
  (vite.config.ts が `src/main.ts` → `app/assets/javascripts/copytuner.js` を出力)。
@@ -21,12 +21,13 @@ module CopyTunerClient
21
21
  @cache = cache
22
22
  @tree_cache = nil
23
23
  @cache_version = nil
24
- end # Translates the given local and key. See the I18n API documentation for details.
24
+ end
25
+
25
26
  #
26
27
  # @return [Object] the translated key (usually a String)
27
28
  def translate(locale, key, options = {})
28
29
  # I18nの標準処理に任せる(内部でlookupが呼ばれる)
29
- content = super(locale, key, options)
30
+ content = super
30
31
 
31
32
  return content if content.nil? || content.is_a?(Hash)
32
33
 
@@ -43,8 +44,9 @@ module CopyTunerClient
43
44
  # @return [Array<String>] available locales
44
45
  def available_locales
45
46
  return @available_locales if defined?(@available_locales)
47
+
46
48
  cached_locales = cache.keys.map { |key| key.split('.').first }
47
- @available_locales = (cached_locales + super).uniq.map { |locale| locale.to_sym }
49
+ @available_locales = (cached_locales + super).uniq.map(&:to_sym)
48
50
  end
49
51
 
50
52
  # Stores the given translations.
@@ -62,7 +64,7 @@ module CopyTunerClient
62
64
 
63
65
  private
64
66
 
65
- def lookup(locale, key, scope = [], options = {})
67
+ def lookup(locale, key, scope = [], options = {}) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
66
68
  return nil if !key.is_a?(String) && !key.is_a?(Symbol)
67
69
 
68
70
  parts = I18n.normalize_keys(locale, key, scope, options[:separator])
@@ -77,8 +79,9 @@ module CopyTunerClient
77
79
  return super
78
80
  end
79
81
 
80
- if CopyTunerClient::configuration.ignored_keys.include?(key_without_locale)
81
- CopyTunerClient::configuration.ignored_key_handler.call(IgnoredKey.new("Ignored key: #{key_without_locale}"))
82
+ config = CopyTunerClient.configuration
83
+ if config.ignored_keys.include?(key_without_locale)
84
+ config.ignored_key_handler.call(IgnoredKey.new("Ignored key: #{key_without_locale}"))
82
85
  end
83
86
 
84
87
  # NOTE: ハッシュ化した場合に削除されるキーに対応するため、最初に完全一致をチェック(旧クライアントの動作を維持)
@@ -114,7 +117,9 @@ module CopyTunerClient
114
117
  def lookup_in_tree_cache(keys)
115
118
  return nil if @tree_cache.nil?
116
119
 
117
- symbol_keys = keys.map(&:to_sym)
120
+ # NOTE: keys は I18n.normalize_keys 済みの配列で、数字だけのセグメントは Integer になっている
121
+ # (例: "...body_temperature.36.5" は [..., 36, 5] に分割される)。Integer#to_sym は無いため to_s を経由する。
122
+ symbol_keys = keys.map { |k| k.to_s.to_sym }
118
123
  begin
119
124
  result = @tree_cache.dig(*symbol_keys)
120
125
  result.is_a?(Hash) ? result : nil
@@ -146,21 +151,22 @@ module CopyTunerClient
146
151
  end
147
152
 
148
153
  def default(locale, object, subject, options = {})
149
- content = super(locale, object, subject, options)
154
+ content = super
150
155
  return content if !object.is_a?(String) && !object.is_a?(Symbol)
151
156
 
152
157
  if content.respond_to?(:to_str)
153
158
  parts = I18n.normalize_keys(locale, object, options[:scope], options[:separator])
154
159
  # NOTE: ActionView::Helpers::TranslationHelper#translate wraps default String in an Array
155
160
  # NOTE: local_first キーのアップロード抑止は Cache#[]= 側に集約している
156
- if subject.is_a?(String) || (subject.is_a?(Array) && subject.size == 1 && subject.first.is_a?(String))
157
- key = parts.join('.')
158
- cache[key] = content.to_str
159
- end
161
+ cache[parts.join('.')] = content.to_str if default_string_subject?(subject)
160
162
  end
161
163
  content
162
164
  end
163
165
 
166
+ def default_string_subject?(subject)
167
+ subject.is_a?(String) || (subject.is_a?(Array) && subject.size == 1 && subject.first.is_a?(String))
168
+ end
169
+
164
170
  attr_reader :cache
165
171
  end
166
172
  end
@@ -1,6 +1,6 @@
1
1
  module CopyTunerClient
2
2
  # Client version
3
- VERSION = '1.2.2'.freeze
3
+ VERSION = '1.2.3'.freeze
4
4
 
5
5
  # API version being used to communicate with the server
6
6
  API_VERSION = '2.0'.freeze
@@ -425,6 +425,23 @@ describe 'CopyTunerClient::I18nBackend' do
425
425
  result = subject.translate('ja', 'hoge.hello', default: nil)
426
426
  expect(result).to be_nil
427
427
  end
428
+
429
+ it '数値セグメントを含むキー(数値enum)でクラッシュしないこと' do
430
+ # NOTE: enumerize の Float range など、normalize_keys が末尾を Integer に分割するキー。
431
+ # exact_match(完全一致)を回避するため別キーを格納し、tree_cache 探索経路を必ず通す。
432
+ cache['ja.dummy'] = 'dummy'
433
+
434
+ expect {
435
+ subject.translate('ja', 'enumerize.infection_control.body_temperature.36.5', default: nil)
436
+ }.not_to raise_error
437
+ end
438
+
439
+ it '数値セグメントキーが存在しても通常キーのlookupが壊れないこと' do
440
+ cache['ja.views.hoge'] = 'normal'
441
+
442
+ expect { subject.translate('ja', 'enumerize.body_temperature.36.5', default: nil) }.not_to raise_error
443
+ expect(subject.translate('ja', 'views.hoge')).to eq('normal')
444
+ end
428
445
  end
429
446
  end
430
447
 
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.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - SonicGarden