From 5670c8c9b91150196757f0b1224d63b6a4228602 Mon Sep 17 00:00:00 2001 From: mix irving Date: Fri, 15 Aug 2014 15:01:58 +1200 Subject: [PATCH 1/2] add interpolation variable matcher --- .../have_interpolation_keys_of_matcher.rb | 22 ++++++++++++++ lib/i18n-spec/models/locale_file.rb | 30 +++++++++++++++++++ spec/fixtures/broken_interpolation_keys.yml | 11 +++++++ spec/fixtures/en.yml | 4 ++- spec/fixtures/es.yml | 4 ++- spec/fixtures/fr.yml | 4 ++- spec/lib/i18n-spec/matchers_spec.rb | 3 ++ spec/lib/i18n-spec/models/locale_file_spec.rb | 6 ++-- 8 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb create mode 100644 spec/fixtures/broken_interpolation_keys.yml diff --git a/lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb b/lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb new file mode 100644 index 0000000..25421ff --- /dev/null +++ b/lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb @@ -0,0 +1,22 @@ +RSpec::Matchers.define :have_interpolation_keys_of do |default_locale_filepath| + extend I18nSpec::FailureMessage + + match do |filepath| + locale_file = I18nSpec::LocaleFile.new(filepath) + default_locale = I18nSpec::LocaleFile.new(default_locale_filepath) + + @superset = locale_file.flattened_and_interpolation_only.keys.reject do |key| + + default_vars = default_locale.flattened_and_interpolation_only[key] + locale_vars = locale_file.flattened_and_interpolation_only[key] + + (locale_vars == default_vars) || locale_vars.empty? + end + + @superset.empty? + end + + failure_for_should do |filepath| + "Expected #{filepath} interpolation variables to match #{default_locale_filepath}. \nProblems in:\n- " << @superset.join("\n- ") + end +end diff --git a/lib/i18n-spec/models/locale_file.rb b/lib/i18n-spec/models/locale_file.rb index cb18b7c..fa96e13 100644 --- a/lib/i18n-spec/models/locale_file.rb +++ b/lib/i18n-spec/models/locale_file.rb @@ -22,6 +22,10 @@ def flattened_translations @flattened_translations ||= flatten_tree(translations.values.first) end + def flattened_and_interpolation_only + @flattened_and_interpolation_only ||= build_interpolations_only_tree(translations.values.first) + end + def locale @locale ||= ISO::Tag.new(locale_code) end @@ -110,6 +114,32 @@ def pluralization_data?(data) keys.any? {|k| PLURALIZATION_KEYS.include?(k) } end + def build_interpolations_only_tree(data, new_tree = {}, key_trace = '') + data.each_pair do |key, value| + extended_key_trace = key_trace + key + + if value.is_a? Hash + new_tree = build_interpolations_only_tree(value, new_tree, extended_key_trace + '.') + else + new_tree[extended_key_trace] = parse_for_variables(value) if contains_variables?(value) + end + end + + new_tree + end + + def contains_variables?(str) + return false if str.nil? + + !parse_for_variables(str).empty? + end + + def parse_for_variables(str) + return nil if str.nil? + + str.scan(/%{[^%{}]*}/) + end + def yaml_load_content if defined?(Psych) and defined?(Psych::VERSION) Psych.load(content) diff --git a/spec/fixtures/broken_interpolation_keys.yml b/spec/fixtures/broken_interpolation_keys.yml new file mode 100644 index 0000000..b757bee --- /dev/null +++ b/spec/fixtures/broken_interpolation_keys.yml @@ -0,0 +1,11 @@ +es: + cats: + zero: 'no gatos' + one: 'un gato' + other: '%{count } gatos' + itteh: + bitteh: + ceiling: + kitteh: 'te mira' + group: + joined: "%{user_name} unido correctamente %{groupo}" \ No newline at end of file diff --git a/spec/fixtures/en.yml b/spec/fixtures/en.yml index fd93e1f..facd364 100644 --- a/spec/fixtures/en.yml +++ b/spec/fixtures/en.yml @@ -7,4 +7,6 @@ en: itteh: bitteh: ceiling: - kitteh: 'is watching you' \ No newline at end of file + kitteh: 'is watching you' + group: + joined: "%{user_name} successfully joined %{group}" \ No newline at end of file diff --git a/spec/fixtures/es.yml b/spec/fixtures/es.yml index c7e473a..8fe2ae5 100644 --- a/spec/fixtures/es.yml +++ b/spec/fixtures/es.yml @@ -6,4 +6,6 @@ es: itteh: bitteh: ceiling: - kitteh: 'te mira' \ No newline at end of file + kitteh: 'te mira' + group: + joined: "%{user_name} unido correctamente %{group}" \ No newline at end of file diff --git a/spec/fixtures/fr.yml b/spec/fixtures/fr.yml index e3035a5..9c7adf7 100644 --- a/spec/fixtures/fr.yml +++ b/spec/fixtures/fr.yml @@ -6,4 +6,6 @@ en: itteh: bitteh: ceiling: - kitteh: 'te regarde' \ No newline at end of file + kitteh: 'te regarde' + group: + joined: # deliberatley empty diff --git a/spec/lib/i18n-spec/matchers_spec.rb b/spec/lib/i18n-spec/matchers_spec.rb index ea91f6b..7c16b59 100644 --- a/spec/lib/i18n-spec/matchers_spec.rb +++ b/spec/lib/i18n-spec/matchers_spec.rb @@ -12,17 +12,20 @@ it { expect('spec/fixtures/legacy_interpolations.yml').to have_legacy_interpolations } it { expect('spec/fixtures/invalid_locale.yml').not_to have_a_valid_locale } it { expect('spec/fixtures/not_subset.yml').not_to be_a_subset_of 'spec/fixtures/en.yml' } + it { expect('spec/fixtures/broken_interpolation_keys.yml').not_to have_interpolation_keys_of 'spec/fixtures/en.yml' } it { expect('spec/fixtures/missing_pluralization_keys.yml').to have_missing_pluralization_keys } end describe "Translated files" do describe 'spec/fixtures/fr.yml' do it { is_expected.to be_a_subset_of 'spec/fixtures/en.yml' } + it { is_expected.to have_interpolation_keys_of 'spec/fixtures/en.yml' } it { is_expected.to be_a_complete_translation_of 'spec/fixtures/en.yml' } end describe 'spec/fixtures/es.yml' do it { is_expected.to be_a_subset_of 'spec/fixtures/en.yml' } + it { is_expected.to have_interpolation_keys_of 'spec/fixtures/en.yml' } it { is_expected.not_to be_a_complete_translation_of 'spec/fixtures/en.yml'} end end diff --git a/spec/lib/i18n-spec/models/locale_file_spec.rb b/spec/lib/i18n-spec/models/locale_file_spec.rb index e968358..2d0ba39 100644 --- a/spec/lib/i18n-spec/models/locale_file_spec.rb +++ b/spec/lib/i18n-spec/models/locale_file_spec.rb @@ -106,7 +106,7 @@ def locale_file_with_content(content) end describe "#missing_pluralization_keys" do - it "returns the parents that containts missing pluralizations in with the english rules" do + it "returns the parents that contains missing pluralizations in with the english rules" do content = "en: cats: one: one @@ -123,7 +123,7 @@ def locale_file_with_content(content) expect(locale_file.errors[:missing_pluralization_keys]).not_to be_nil end - it "returns the parents that containts missing pluralizations in with the russian rules" do + it "returns the parents that contains missing pluralizations in with the russian rules" do content = "ru: cats: one: one @@ -146,7 +146,7 @@ def locale_file_with_content(content) expect(locale_file.errors[:missing_pluralization_keys]).not_to be_nil end - it "returns the parents that containts missing pluralizations in with the japanese rules" do + it "returns the parents that contains missing pluralizations in with the japanese rules" do content = "ja: cats: one: one From 470cffa3c83ac9e44811cb957ca36444df948f2b Mon Sep 17 00:00:00 2001 From: mix irving Date: Sat, 30 Aug 2014 23:57:28 +1200 Subject: [PATCH 2/2] tidyup --- .../have_interpolation_keys_of_matcher.rb | 16 ++++++------ lib/i18n-spec/models/locale_file.rb | 26 +++++++------------ lib/i18n-spec/models/parse.rb | 10 +++++++ spec/fixtures/fr.yml | 2 +- spec/fixtures/interpolation_missing.yml | 11 ++++++++ ...on_keys.yml => interpolation_misspelt.yml} | 0 spec/lib/i18n-spec/matchers_spec.rb | 3 ++- 7 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 lib/i18n-spec/models/parse.rb create mode 100644 spec/fixtures/interpolation_missing.yml rename spec/fixtures/{broken_interpolation_keys.yml => interpolation_misspelt.yml} (100%) diff --git a/lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb b/lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb index 25421ff..5b4b9ed 100644 --- a/lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb +++ b/lib/i18n-spec/matchers/have_interpolation_keys_of_matcher.rb @@ -1,16 +1,16 @@ RSpec::Matchers.define :have_interpolation_keys_of do |default_locale_filepath| extend I18nSpec::FailureMessage - match do |filepath| - locale_file = I18nSpec::LocaleFile.new(filepath) - default_locale = I18nSpec::LocaleFile.new(default_locale_filepath) + match do |test_locale_filepath| + default_translations = I18nSpec::LocaleFile.new(default_locale_filepath).flat_interpolations_only_hash + test_translations = I18nSpec::LocaleFile.new(test_locale_filepath).flat_interpolations_only_hash - @superset = locale_file.flattened_and_interpolation_only.keys.reject do |key| + @superset = default_translations.keys.reject do |key| + default_value = default_translations[key] + test_value = test_translations[key] - default_vars = default_locale.flattened_and_interpolation_only[key] - locale_vars = locale_file.flattened_and_interpolation_only[key] - - (locale_vars == default_vars) || locale_vars.empty? + test_value.nil? || + I18nSpec::Parse.for_interpolation_variables(default_value) == I18nSpec::Parse.for_interpolation_variables(test_value) end @superset.empty? diff --git a/lib/i18n-spec/models/locale_file.rb b/lib/i18n-spec/models/locale_file.rb index fa96e13..8feac74 100644 --- a/lib/i18n-spec/models/locale_file.rb +++ b/lib/i18n-spec/models/locale_file.rb @@ -22,8 +22,8 @@ def flattened_translations @flattened_translations ||= flatten_tree(translations.values.first) end - def flattened_and_interpolation_only - @flattened_and_interpolation_only ||= build_interpolations_only_tree(translations.values.first) + def flat_interpolations_only_hash + @flat_interpolations_only_hash ||= build_interpolations_only_hash(translations.values.first) end def locale @@ -114,30 +114,22 @@ def pluralization_data?(data) keys.any? {|k| PLURALIZATION_KEYS.include?(k) } end - def build_interpolations_only_tree(data, new_tree = {}, key_trace = '') + def build_interpolations_only_hash(data, prefix = '', result = {}) data.each_pair do |key, value| - extended_key_trace = key_trace + key - - if value.is_a? Hash - new_tree = build_interpolations_only_tree(value, new_tree, extended_key_trace + '.') + current_prefix = prefix.empty? ? key.to_s : "#{prefix}.#{key}" + if !value.is_a? Hash + result[current_prefix] = value #if contains_variables?(value) else - new_tree[extended_key_trace] = parse_for_variables(value) if contains_variables?(value) + result = build_interpolations_only_hash(value, current_prefix, result) end end - new_tree + result end def contains_variables?(str) return false if str.nil? - - !parse_for_variables(str).empty? - end - - def parse_for_variables(str) - return nil if str.nil? - - str.scan(/%{[^%{}]*}/) + !I18nSpec::Parse.for_interpolation_variables(str).empty? end def yaml_load_content diff --git a/lib/i18n-spec/models/parse.rb b/lib/i18n-spec/models/parse.rb new file mode 100644 index 0000000..1ebfba6 --- /dev/null +++ b/lib/i18n-spec/models/parse.rb @@ -0,0 +1,10 @@ +module I18nSpec + class Parse + + def self.for_interpolation_variables(str) + return nil if str.nil? + str.scan(/%{[^%{}]*}/) + end + + end +end \ No newline at end of file diff --git a/spec/fixtures/fr.yml b/spec/fixtures/fr.yml index 9c7adf7..f41e9fa 100644 --- a/spec/fixtures/fr.yml +++ b/spec/fixtures/fr.yml @@ -8,4 +8,4 @@ en: ceiling: kitteh: 'te regarde' group: - joined: # deliberatley empty + joined: # deliberatley empty translation for interpolation variable checker diff --git a/spec/fixtures/interpolation_missing.yml b/spec/fixtures/interpolation_missing.yml new file mode 100644 index 0000000..e64131b --- /dev/null +++ b/spec/fixtures/interpolation_missing.yml @@ -0,0 +1,11 @@ +es: + cats: + zero: 'no gatos' + one: 'un gato' + other: 'gatos' + itteh: + bitteh: + ceiling: + kitteh: 'te mira' + group: + joined: "(interpolation should var should be here) unido correctamente" \ No newline at end of file diff --git a/spec/fixtures/broken_interpolation_keys.yml b/spec/fixtures/interpolation_misspelt.yml similarity index 100% rename from spec/fixtures/broken_interpolation_keys.yml rename to spec/fixtures/interpolation_misspelt.yml diff --git a/spec/lib/i18n-spec/matchers_spec.rb b/spec/lib/i18n-spec/matchers_spec.rb index 7c16b59..5182fd5 100644 --- a/spec/lib/i18n-spec/matchers_spec.rb +++ b/spec/lib/i18n-spec/matchers_spec.rb @@ -12,7 +12,8 @@ it { expect('spec/fixtures/legacy_interpolations.yml').to have_legacy_interpolations } it { expect('spec/fixtures/invalid_locale.yml').not_to have_a_valid_locale } it { expect('spec/fixtures/not_subset.yml').not_to be_a_subset_of 'spec/fixtures/en.yml' } - it { expect('spec/fixtures/broken_interpolation_keys.yml').not_to have_interpolation_keys_of 'spec/fixtures/en.yml' } + it { expect('spec/fixtures/interpolation_misspelt.yml').not_to have_interpolation_keys_of 'spec/fixtures/en.yml' } + it { expect('spec/fixtures/interpolation_missing.yml').not_to have_interpolation_keys_of 'spec/fixtures/en.yml' } it { expect('spec/fixtures/missing_pluralization_keys.yml').to have_missing_pluralization_keys } end