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..5b4b9ed --- /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 |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 = default_translations.keys.reject do |key| + default_value = default_translations[key] + test_value = test_translations[key] + + test_value.nil? || + I18nSpec::Parse.for_interpolation_variables(default_value) == I18nSpec::Parse.for_interpolation_variables(test_value) + 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..8feac74 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 flat_interpolations_only_hash + @flat_interpolations_only_hash ||= build_interpolations_only_hash(translations.values.first) + end + def locale @locale ||= ISO::Tag.new(locale_code) end @@ -110,6 +114,24 @@ def pluralization_data?(data) keys.any? {|k| PLURALIZATION_KEYS.include?(k) } end + def build_interpolations_only_hash(data, prefix = '', result = {}) + data.each_pair do |key, value| + current_prefix = prefix.empty? ? key.to_s : "#{prefix}.#{key}" + if !value.is_a? Hash + result[current_prefix] = value #if contains_variables?(value) + else + result = build_interpolations_only_hash(value, current_prefix, result) + end + end + + result + end + + def contains_variables?(str) + return false if str.nil? + !I18nSpec::Parse.for_interpolation_variables(str).empty? + end + def yaml_load_content if defined?(Psych) and defined?(Psych::VERSION) Psych.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/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..f41e9fa 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 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/interpolation_misspelt.yml b/spec/fixtures/interpolation_misspelt.yml new file mode 100644 index 0000000..b757bee --- /dev/null +++ b/spec/fixtures/interpolation_misspelt.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/lib/i18n-spec/matchers_spec.rb b/spec/lib/i18n-spec/matchers_spec.rb index ea91f6b..5182fd5 100644 --- a/spec/lib/i18n-spec/matchers_spec.rb +++ b/spec/lib/i18n-spec/matchers_spec.rb @@ -12,17 +12,21 @@ 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/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 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