Permalink
Browse files

Merge pull request #19 from freetwix/feature/pluralization

fixed pluralization handling
  • Loading branch information...
2 parents 93e6210 + 0631b89 commit 925fcb667bc27ce537a4564c9ac2dc3fb475a29f @thomasdarde thomasdarde committed Sep 11, 2012
View
1 .rvmrc
@@ -0,0 +1 @@
+rvm --create ruby-1.9.3-p194@tolk
@@ -64,7 +64,8 @@ def special_key_or_prefix?(prefix, key)
self.special_prefixes.include?(prefix) || self.special_keys.include?(key)
end
- PLURALIZATION_KEYS = ['none', 'one', 'two', 'few', 'many', 'other']
+ # http://cldr.unicode.org/index/cldr-spec/plural-rules - TODO: usage of 'none' isn't standard-conform
+ PLURALIZATION_KEYS = ['none', 'zero', 'one', 'two', 'few', 'many', 'other']
def pluralization_data?(data)
keys = data.keys.map(&:to_s)
keys.all? {|k| PLURALIZATION_KEYS.include?(k) }
@@ -57,12 +57,20 @@ def value
end
def self.detect_variables(search_in)
- case search_in
+ variables = case search_in
when String then Set.new(search_in.scan(/\{\{(\w+)\}\}/).flatten + search_in.scan(/\%\{(\w+)\}/).flatten)
when Array then search_in.inject(Set[]) { |carry, item| carry + detect_variables(item) }
when Hash then search_in.values.inject(Set[]) { |carry, item| carry + detect_variables(item) }
else Set[]
end
+
+ # delete special i18n variable used for pluralization itself (might not be used in all values of
+ # the pluralization keys, but is essential to use pluralization at all)
+ if search_in.is_a?(Hash) && Tolk::Locale.pluralization_data?(search_in)
+ variables.delete_if {|v| v == 'count' }
+ else
+ variables
+ end
end
def variables
@@ -110,10 +118,10 @@ def set_previous_text
def check_matching_variables
unless variables_match?
- if primary_translation.variables.empty? || primary_translation.variables.class == Set
- self.errors.add(:text, "The original does not contain variables, so they should not be included.")
+ if primary_translation.variables.empty?
+ self.errors.add(:variables, "The primary translation does not contain substitutions, so this should neither.")
else
- self.errors.add(:text, "The translation should contain the variables #{primary_translation.to_a.to_sentence}.")
+ self.errors.add(:variables, "The translation should contain the substitutions of the primary translation: (#{primary_translation.variables.to_a.join(', ')}), found (#{self.variables.to_a.join(', ')}).")
end
end
end
View
@@ -8,13 +8,13 @@ module ClassMethods
def import_secondary_locales
locales = Dir.entries(self.locales_config_path)
-
- locale_block_filter = Proc.new {
+
+ locale_block_filter = Proc.new {
|l| ['.', '..'].include?(l) ||
!l.ends_with?('.yml') ||
l.match(/(.*\.){2,}/) # reject files of type xxx.en.yml
}
- locales = locales.reject(&locale_block_filter).map {|x| x.split('.').first }
+ locales = locales.reject(&locale_block_filter).map {|x| x.split('.').first }
locales = locales - [Tolk::Locale.primary_locale.name]
locales.each {|l| import_locale(l) }
end
@@ -32,9 +32,13 @@ def import_locale(locale_name)
if phrase
translation = locale.translations.new(:text => value, :phrase => phrase)
- count = count + 1 if translation.save
+ if translation.save
+ count = count + 1
+ elsif translation.errors[:variables].present?
+ puts "[WARN] Key '#{key}' from '#{locale_name}.yml' could not be saved: #{translation.errors[:variables].first}"
+ end
else
- puts "[ERROR] Key '#{key}' was found in #{locale_name}.yml but #{Tolk::Locale.primary_language_name} translation is missing"
+ puts "[ERROR] Key '#{key}' was found in '#{locale_name}.yml' but #{Tolk::Locale.primary_language_name} translation is missing"
end
end
@@ -9,7 +9,13 @@ en:
number_array: [1, 2, 3]
string_array: ['sun', 'moon']
pluralization:
- other: Hello
+ none: none
+ zero: zero
+ one: one
+ two: two
+ few: few
+ many: many
+ other: other
not_pluralization:
other: World
lifo: fifo
View
@@ -27,11 +27,19 @@ def test_all_formats_are_loaded_properly
assert_equal ['sun', 'moon'], @en.get('string_array')
end
- def test_pluaralization
- result = {'other' => 'Hello'}
+ def test_pluralization
+ result = {
+ "none" => "none",
+ "zero" => "zero",
+ "one" => "one",
+ "two" => "two",
+ "few" => "few",
+ "many" => "many",
+ "other" => "other"
+ }
assert_equal result, @en.get('pluralization')
- assert ! @en.get('not_pluralization')
+ assert_nil @en.get('not_pluralization')
assert_equal 'World', @en.get('not_pluralization.other')
assert_equal 'fifo', @en.get('not_pluralization.lifo')
end
View
@@ -19,10 +19,7 @@ def setup
test "skips gem translations files (xxx.en.yml)" do
Tolk::Locale.sync!
Tolk::Locale.import_secondary_locales
-
assert_equal 0, Tolk::Phrase.where(key: 'gem_hello_world').count
-
end
-
end
@@ -9,36 +9,77 @@ def setup
end
test "translation is inavlid when a duplicate exists" do
- translation = Tolk::Translation.new :phrase => tolk_translations(:hello_world_da).phrase, :locale => tolk_translations(:hello_world_da).locale
+ translation = Tolk::Translation.new(:phrase => tolk_translations(:hello_world_da).phrase, :locale => tolk_translations(:hello_world_da).locale)
translation.text = "Revised Hello World"
- assert translation.invalid?
- assert translation.errors[:phrase_id]
+ assert(translation.invalid?)
+ assert(translation.errors[:phrase_id])
end
-
+
test "translation is not changed when text is assigned an equal value in numberic form" do
translation = tolk_translations(:human_format_precision_en)
- assert_equal "1", translation.text
+ assert_equal("1", translation.text)
translation.text = "1"
- assert_equal false, translation.changed?
+ assert_equal(false, translation.changed?)
translation.text = 1
- assert_equal false, translation.changed?
+ assert_equal(false, translation.changed?)
end
test "translation with string value" do
- assert_equal "Hello World", tolk_translations(:hello_world_en).value
+ assert_equal("Hello World", tolk_translations(:hello_world_en).value)
end
test "translation with string value with variables" do
text = "{{attribute}} {{message}}"
- assert_equal text, Tolk::Translation.new(:text => text).value
+ assert_equal(text, Tolk::Translation.new(:text => text).value)
end
test "translation with numeric value" do
- assert_equal 1, tolk_translations(:human_format_precision_en).value
+ assert_equal(1, tolk_translations(:human_format_precision_en).value)
end
-
+
test "translation with hash value" do
hash = {:foo => "bar"}
- assert_equal hash, Tolk::Translation.new(:text => hash).value
+ assert_equal(hash, Tolk::Translation.new(:text => hash).value)
+ end
+
+ test "pluralization translation special variable 'count' not a variable" do
+ text = {
+ 'zero' => "{{message}}",
+ 'many' => "{{message}} {{count}}",
+ 'other' => "{{message}} {{count}}"
+ }
+ assert_equal(Set['message'], Tolk::Translation.detect_variables(text))
+ end
+
+ test "validation for variables (mismatch)" do
+ primary_text = {
+ 'zero' => "{{message}}",
+ 'many' => "{{message}} {{count}}",
+ }
+ text = {
+ 'zero' => "{{message}}",
+ 'many' => "{{foo}}",
+ }
+
+ Tolk::Translation.new(:text => text).tap do |t|
+ t.stubs(:primary_translation).returns(Tolk::Translation.new(:text => primary_text))
+ t.valid?
+ assert_equal ["The translation should contain the substitutions of the primary translation: (message), found (message, foo)."], t.errors[:variables]
+ end
+ end
+
+ test "validation for variables (no variables in primary)" do
+ primary_text = {
+ 'foo' => "nada"
+ }
+ text = {
+ 'foo' => "{{foo}} nada"
+ }
+
+ Tolk::Translation.new(:text => text).tap do |t|
+ t.stubs(:primary_translation).returns(Tolk::Translation.new(:text => primary_text))
+ t.valid?
+ assert_equal ["The primary translation does not contain substitutions, so this should neither."], t.errors[:variables]
+ end
end
end

0 comments on commit 925fcb6

Please sign in to comment.