有两个 Ruby on Rails 国际化的 YAML 文件。其中一个文件是完整的,另一个文件则有一些缺失的键。我该如何比较这两个 YAML 文件,并查看第二个文件中缺失的键?是否有工具可以做到这一点?
有两个 Ruby on Rails 国际化的 YAML 文件。其中一个文件是完整的,另一个文件则有一些缺失的键。我该如何比较这两个 YAML 文件,并查看第二个文件中缺失的键?是否有工具可以做到这一点?
假设file1
是正确的版本,而file2
是缺少键值的版本:
def compare_yaml_hash(cf1, cf2, context = [])
cf1.each do |key, value|
unless cf2.key?(key)
puts "Missing key : #{key} in path #{context.join(".")}"
next
end
value2 = cf2[key]
if (value.class != value2.class)
puts "Key value type mismatch : #{key} in path #{context.join(".")}"
next
end
if value.is_a?(Hash)
compare_yaml_hash(value, value2, (context + [key]))
next
end
if (value != value2)
puts "Key value mismatch : #{key} in path #{context.join(".")}"
end
end
end
现在
compare_yaml_hash(YAML.load_file("file1"), YAML.load_file("file2"))
限制:如果您的YAML文件包含数组,则当前实现应该扩展以支持数组。
rails console; I18n.translate(:foo); en = I18n.backend.send(:translations)[:en]; de = I18n.backend.send(:translations)[:de]; compare_yaml_hash(en, de, [])
。 translate(:foo)
是为了强制加载翻译。使用此函数,不同语言将会有许多“键值不匹配”的情况;如果只关心缺少的键,请注释该行。也可以反向运行它。 - Nathan LongI18n.backend
- 它可能有一些键不在你想比较的文件中。 - Nathan LongI18n.backend.send(:init_translations)
可以强制I18n初始化,而不是使用I18n.translate(:foo)
,具体情况可能有所不同。 - Jonas Schubert Erlandssondifferz可以比较两个YAML文件并打印第二个文件中缺失的键。
differz show file1.yml file2.yml
gem install differz
安装后者。$ cabal update
$ cabal install yamlkeysdiff
$ yamlkeysdiff file1.yml file2.yml
> missing key in file2
< missing key in file1
$ yamlkeysdiff "file1.yml#key:subkey" "file2.yml#otherkey"
diff
完全相同,您可以这样做:$ yamlkeysdiff file1.yml file2.yml && echo Is the same || echo Is different
def deep_hash_diff(hash1, hash2, hash1_name = 'Hash 1', hash2_name = 'Hash 2')
diff = {}
(hash1.keys - hash2.keys).each do |key1|
diff[key1] = "Present in #{hash1_name}, but not in #{hash2_name}"
end
(hash2.keys - hash1.keys).each do |key2|
diff[key2] = "Present in #{hash2_name}, but not in #{hash1_name}"
end
(hash1.keys & hash2.keys).each do |common_key|
if hash1[common_key].is_a?(Hash)
if hash2[common_key].is_a?(Hash)
res = deep_hash_diff(hash1[common_key], hash2[common_key], hash1_name, hash2_name)
diff[common_key] = res if res.present?
else
diff[common_key] = "#{hash1_name} has nested hash, but #{hash2_name} just value #{hash2[common_key]}"
end
elsif hash2[common_key].is_a?(Hash)
diff[common_key] = "#{hash2_name} has nested hash, but #{hash1_name} just value #{hash1[common_key]}"
end
end
diff
end
我之后基本上就这样使用它:
res = deep_hash_diff(YAML.load_file("en.yml"), YAML.load_file("spa.yml"), 'English translation', 'Spanish translation')
puts(res.to_yaml) # for nicer output