Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@
"cSpell.words": [
"mkpath"
],
"[ruby]": {
"editor.defaultFormatter": "rubocop.vscode-rubocop",
}
}
26 changes: 22 additions & 4 deletions lib/copy_tuner_client/dotted_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ module DottedHash
def to_h(dotted_hash)
hash = {}
dotted_hash.to_h.transform_keys(&:to_s).sort.each do |key, value|
_hash = key.split('.').reverse.inject(value) { |memo, key| { key => memo } }
# Rails i18n標準との互換性のため、特定のキーを適切な型に変換
converted_value = convert_value_type(key, value)
_hash = key.split('.').reverse.inject(converted_value) { |memo, _key| { _key => memo } }
hash.deep_merge!(_hash)
end
hash
Expand All @@ -16,8 +18,8 @@ def conflict_keys(dotted_hash)
all_keys.each_with_index do |key, index|
prefix = "#{key}."
conflict_keys = ((index + 1)..Float::INFINITY)
.take_while { |i| all_keys[i]&.start_with?(prefix) }
.map { |i| all_keys[i] }
.take_while { |i| all_keys[i]&.start_with?(prefix) }
.map { |i| all_keys[i] }

if conflict_keys.present?
results[key] = conflict_keys
Expand All @@ -27,6 +29,22 @@ def conflict_keys(dotted_hash)
results
end

module_function :to_h, :conflict_keys
private

def convert_value_type(key, value)
return value unless value.is_a?(String)

# Rails i18n標準で数値型として扱われるキー
if key.end_with?('.precision')
value.to_i
# Rails i18n標準で真偽値として扱われるキー
elsif key.end_with?('.significant', '.strip_insignificant_zeros')
value == 'true'
else
value
end
end

module_function :to_h, :conflict_keys, :convert_value_type # rubocop:disable Style/AccessModifierDeclarations
end
end
7 changes: 3 additions & 4 deletions lib/copy_tuner_client/i18n_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,9 @@ def lookup(locale, key, scope = [], options = {})
return exact_match
end

# NOTE: 色々考慮する必要があることが分かったため暫定対応として、ツリーキャッシュを使用しないようにしている
# ensure_tree_cache_current
# tree_result = lookup_in_tree_cache(parts)
# return tree_result if tree_result
ensure_tree_cache_current
tree_result = lookup_in_tree_cache(parts)
return tree_result if tree_result

content = super

Expand Down
92 changes: 83 additions & 9 deletions spec/copy_tuner_client/dotted_hash_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@
describe ".to_h" do
subject { CopyTunerClient::DottedHash.to_h(dotted_hash) }

context 'empty keys' do
context '空のキーの場合' do
let(:dotted_hash) { {} }

it { is_expected.to eq({}) }
end

context 'with single-level keys' do
context '1階層のキーの場合' do
let(:dotted_hash) { { 'key' => 'test value', other_key: 'other value' } }

it { is_expected.to eq({ 'key' => 'test value', 'other_key' => 'other value' }) }
end

context 'array of key value pairs' do
context 'キーと値の配列の場合' do
let(:dotted_hash) { [['key', 'test value'], ['other_key', 'other value']] }

it { is_expected.to eq({ 'key' => 'test value', 'other_key' => 'other value' }) }
end

context "with multi-level blurb keys" do
context "複数階層のblurbキーの場合" do
let(:dotted_hash) do
{
'en.test.key' => 'en test value',
Expand All @@ -31,7 +31,7 @@
}
end

it do
it "正しくネストされたハッシュに変換されること" do
is_expected.to eq({
'en' => {
'test' => {
Expand All @@ -48,7 +48,7 @@
end
end

context "with conflicting keys" do
context "キーの競合がある場合" do
let(:dotted_hash) do
{
'en.test' => 'invalid value',
Expand All @@ -58,12 +58,86 @@

it { is_expected.to eq({ 'en' => { 'test' => { 'key' => 'en test value' } } }) }
end

context "Rails i18nの数値precisionキーの場合" do
let(:dotted_hash) do
{
'en.number.currency.format.precision' => '2',
'en.number.format.precision' => '3',
}
end

it "precision値を整数に変換する" do
is_expected.to eq({
'en' => {
'number' => {
'currency' => {
'format' => {
'precision' => 2,
},
},
'format' => {
'precision' => 3,
},
},
},
})
end
end

context "Rails i18nのbooleanキーの場合" do
let(:dotted_hash) do
{
'en.number.currency.format.significant' => 'false',
'en.number.format.strip_insignificant_zeros' => 'true',
}
end

it "boolean値を実際の真偽値に変換する" do
is_expected.to eq({
'en' => {
'number' => {
'currency' => {
'format' => {
'significant' => false,
},
},
'format' => {
'strip_insignificant_zeros' => true,
},
},
},
})
end
end

context "Rails i18n以外で似たパターンを含むキーの場合" do
let(:dotted_hash) do
{
'en.custom.precision' => 'custom_value',
'en.other.significant_value' => 'true',
}
end

it "Rails i18nパターンで終わるキーのみ変換する" do
is_expected.to eq({
'en' => {
'custom' => {
'precision' => 0, # .precision suffix triggers conversion
},
'other' => {
'significant_value' => 'true', # no conversion for non-exact match
},
},
})
end
end
end

describe ".conflict_keys" do
subject { CopyTunerClient::DottedHash.conflict_keys(dotted_hash) }

context 'valid keys' do
context '有効なキーの場合' do
let(:dotted_hash) do
{
'ja.hoge.test' => 'test',
Expand All @@ -74,7 +148,7 @@
it { is_expected.to eq({}) }
end

context 'invalid keys' do
context '無効なキーの場合' do
let(:dotted_hash) do
{
'ja.hoge.test' => 'test',
Expand All @@ -85,7 +159,7 @@
}
end

it do
it "競合するキーが正しく検出されること" do
is_expected.to eq({
'ja.fuga.test' => %w[ja.fuga.test.hoge],
'ja.hoge.test' => %w[ja.hoge.test.fuga ja.hoge.test.hoge],
Expand Down
2 changes: 1 addition & 1 deletion spec/copy_tuner_client/i18n_backend_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def build_backend
end

# NOTE: 色々考慮する必要があることが分かったため暫定対応として、ツリーキャッシュを使用しないようにしている
xdescribe 'ツリー構造のlookup' do # rubocop:disable Metrics/BlockLength
describe 'ツリー構造のlookup' do # rubocop:disable Metrics/BlockLength
subject { build_backend }

context '完全一致が存在する場合' do
Expand Down