Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Massive work on gettext API:

* add proper aliases and method names
* add missing npgettext implementation
* add array-syntax support for pluralization
* refactorings throughout
  • Loading branch information...
commit 35a1740d2f10b808548af352006950da4017e374 1 parent 4c88122
@clemens clemens authored
View
16 lib/i18n/backend/gettext.rb
@@ -41,15 +41,25 @@ def parse(filename)
def normalize(locale, data)
data.inject({}) do |result, (key, value)|
- key, value = normalize_pluralization(locale, key, value) if key.index("\000")
- result[key] = value
+ unless key.blank?
+ key, value = normalize_pluralization(locale, key, value) if key.index("\000")
+
+ parts = key.split('|').reverse
+ normalized = parts.inject({}) do |normalized, part|
+ normalized = { part => normalized.empty? ? value : normalized }
+ end
+
+ # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
+ result.merge!(normalized, &merger)
+ end
result
end
end
def normalize_pluralization(locale, key, value)
# FIXME po_parser includes \000 chars that can not be turned into Symbols
- key = key.dup.gsub("\000", I18n::Gettext::PLURAL_SEPARATOR)
+ key = key.gsub("\000", I18n::Gettext::PLURAL_SEPARATOR).split(I18n::Gettext::PLURAL_SEPARATOR).first
keys = I18n::Gettext.plural_keys(locale)
values = value.split("\000")
View
4 lib/i18n/gettext.rb
@@ -15,8 +15,8 @@ def plural_keys(locale)
@@plural_keys[locale] || @@plural_keys[:en]
end
- def extract_scope(msgid, separator = nil)
- scope = msgid.to_s.split(separator || '|')
+ def extract_scope(msgid, separator)
+ scope = msgid.to_s.split(separator)
msgid = scope.pop
[scope, msgid]
end
View
39 lib/i18n/helpers/gettext.rb
@@ -7,29 +7,58 @@ module Helpers
#
# include I18n::Helpers::Gettext
module Gettext
- def _(msgid, options = {})
+ def gettext(msgid, options = {})
I18n.t(msgid, { :default => msgid, :separator => '|' }.merge(options))
end
+ alias _ gettext
def sgettext(msgid, separator = '|')
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
I18n.t(msgid, :scope => scope, :default => msgid)
end
+ alias s_ sgettext
- def pgettext(msgctxt, msgid, separator = I18n::Gettext::CONTEXT_SEPARATOR)
+ def pgettext(msgctxt, msgid)
+ separator = I18n::Gettext::CONTEXT_SEPARATOR
sgettext([msgctxt, msgid].join(separator), separator)
end
+ alias p_ pgettext
def ngettext(msgid, msgid_plural, n = 1)
- nsgettext(msgid, msgid_plural, n, nil)
+ nsgettext(msgid, msgid_plural, n)
end
+ alias n_ ngettext
+
+ # Method signatures:
+ # nsgettext('Fruits|apple', 'apples', 2)
+ # nsgettext(['Fruits|apple', 'apples'], 2)
+ def nsgettext(msgid, msgid_plural, n = 1, separator = '|')
+ if msgid.is_a?(Array)
+ msgid, msgid_plural, n, separator = msgid[0], msgid[1], msgid_plural, n
+ separator = '|' unless separator.is_a?(String)
+ end
- def nsgettext(msgid, msgid_plural, n = 1, separator = nil)
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
default = { :one => msgid, :other => msgid_plural }
- msgid = [msgid, I18n::Gettext::PLURAL_SEPARATOR, msgid_plural].join
I18n.t(msgid, :default => default, :count => n, :scope => scope)
end
+ alias ns_ nsgettext
+
+ # Method signatures:
+ # npgettext('Fruits', 'apple', 'apples', 2)
+ # npgettext('Fruits', ['apple', 'apples'], 2)
+ def npgettext(msgctxt, msgid, msgid_plural, n = 1)
+ separator = I18n::Gettext::CONTEXT_SEPARATOR
+
+ if msgid.is_a?(Array)
+ msgid_plural, msgid, n = msgid[1], [msgctxt, msgid[0]].join(separator), msgid_plural
+ else
+ msgid = [msgctxt, msgid].join(separator)
+ end
+
+ nsgettext(msgid, msgid_plural, n, separator)
+ end
+ alias np_ npgettext
end
end
end
View
6 test/fixtures/locales/de.po
@@ -59,3 +59,9 @@ msgid "this is a dynamic translation which was found thorugh gettext_test_log!"
msgstr ""
"Dies ist eine dynamische Übersetzung, die durch gettext_test_log "
"gefunden wurde!"
+
+#: app/views/cars/nowhere_really
+msgid "Car|wheel"
+msgid_plural "Car|wheels"
+msgstr[0] "Rad"
+msgstr[1] "Räder"
View
154 test/gettext/api_test.rb
@@ -12,67 +12,193 @@ def setup
I18n.backend.store_translations :de, {
'Hi Gettext!' => 'Hallo Gettext!',
'Sentence 1. Sentence 2.' => 'Satz 1. Satz 2.',
- "An apple#{I18n::Gettext::PLURAL_SEPARATOR}{{count}} apples" => { :one => 'Ein Apfel', :other => '{{count}} Äpfel' },
- :special => { 'An apple' => { :one => 'Ein spezieller Apfel', :other => '{{count}} spezielle Äpfel' } },
- :foo => { :bar => { :baz => 'baz-de' } }
+ # "An apple#{I18n::Gettext::PLURAL_SEPARATOR}{{count}} apples" => { :one => 'Ein Apfel', :other => '{{count}} Äpfel' },
+ # :special => { "A special apple#{I18n::Gettext::PLURAL_SEPARATOR}{{count}} special apples" => { :one => 'Ein spezieller Apfel', :other => '{{count}} spezielle Äpfel' } },
+ # alternative implementation
+ "An apple" => { :one => 'Ein Apfel', :other => '{{count}} Äpfel' },
+ :special => { "A special apple" => { :one => 'Ein spezieller Apfel', :other => '{{count}} spezielle Äpfel' } },
+ :foo => { :bar => 'bar-de' }
}
end
- def test_helper_uses_msg_as_default
+ # gettext
+ def test_gettext_uses_msg_as_default
assert_equal 'Hi Gettext!', _('Hi Gettext!')
end
- def test_helper_uses_msg_as_key
+ def test_gettext_uses_msg_as_key
I18n.locale = :de
+ assert_equal 'Hallo Gettext!', gettext('Hi Gettext!')
assert_equal 'Hallo Gettext!', _('Hi Gettext!')
end
- def test_helper_uses_msg_containing_dots_as_default
+ def test_gettext_uses_msg_containing_dots_as_default
+ assert_equal 'Sentence 1. Sentence 2.', gettext('Sentence 1. Sentence 2.')
assert_equal 'Sentence 1. Sentence 2.', _('Sentence 1. Sentence 2.')
end
- def test_helper_uses_msg_containing_dots_as_key
+ def test_gettext_uses_msg_containing_dots_as_key
I18n.locale = :de
+ assert_equal 'Satz 1. Satz 2.', gettext('Sentence 1. Sentence 2.')
assert_equal 'Satz 1. Satz 2.', _('Sentence 1. Sentence 2.')
end
+ # sgettext
def test_sgettext_defaults_to_the_last_token_of_a_scoped_msgid
- assert_equal 'baz', sgettext('foo|bar|baz')
+ assert_equal 'bar', sgettext('foo|bar')
+ assert_equal 'bar', s_('foo|bar')
end
def test_sgettext_looks_up_a_scoped_translation
I18n.locale = :de
- assert_equal 'baz-de', sgettext('foo|bar|baz')
+ assert_equal 'bar-de', sgettext('foo|bar')
+ assert_equal 'bar-de', s_('foo|bar')
end
+ # pgettext
def test_pgettext_defaults_to_msgid
- assert_equal 'baz', pgettext('foo|bar', 'baz', '|')
+ assert_equal 'bar', pgettext('foo', 'bar')
+ assert_equal 'bar', p_('foo', 'bar')
end
def test_pgettext_looks_up_a_scoped_translation
I18n.locale = :de
- assert_equal 'baz-de', pgettext('foo|bar', 'baz', '|')
+ assert_equal 'bar-de', pgettext('foo', 'bar')
+ assert_equal 'bar-de', p_('foo', 'bar')
end
+ # ngettext
def test_ngettext_looks_up_msg_id_as_default_singular
assert_equal 'An apple', ngettext('An apple', '{{count}} apples', 1)
+ assert_equal 'An apple', n_('An apple', '{{count}} apples', 1)
end
def test_ngettext_looks_up_msg_id_plural_as_default_plural
assert_equal '2 apples', ngettext('An apple', '{{count}} apples', 2)
+ assert_equal '2 apples', n_('An apple', '{{count}} apples', 2)
end
- def test_ngettext_looks_up_msg_id_as_singular
+ def test_ngettext_looks_up_a_singular
I18n.locale = :de
assert_equal 'Ein Apfel', ngettext('An apple', '{{count}} apples', 1)
+ assert_equal 'Ein Apfel', n_('An apple', '{{count}} apples', 1)
end
- def test_ngettext_looks_up_msg_id_as_singular
+ def test_ngettext_looks_up_a_plural
I18n.locale = :de
assert_equal '2 Äpfel', ngettext('An apple', '{{count}} apples', 2)
+ assert_equal '2 Äpfel', n_('An apple', '{{count}} apples', 2)
end
+ def test_ngettext_looks_up_msg_id_as_default_singular_with_alternative_syntax
+ assert_equal 'An apple', ngettext(['An apple', '{{count}} apples'], 1)
+ assert_equal 'An apple', n_(['An apple', '{{count}} apples'], 1)
+ end
+
+ def test_ngettext_looks_up_msg_id_plural_as_default_plural_with_alternative_syntax
+ assert_equal '2 apples', ngettext(['An apple', '{{count}} apples'], 2)
+ assert_equal '2 apples', n_(['An apple', '{{count}} apples'], 2)
+ end
+
+ def test_ngettext_looks_up_a_singular_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal 'Ein Apfel', ngettext(['An apple', '{{count}} apples'], 1)
+ assert_equal 'Ein Apfel', n_(['An apple', '{{count}} apples'], 1)
+ end
+
+ def test_ngettext_looks_up_a_plural_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal '2 Äpfel', ngettext(['An apple', '{{count}} apples'], 2)
+ assert_equal '2 Äpfel', n_(['An apple', '{{count}} apples'], 2)
+ end
+
+ # nsgettext
def test_nsgettext_looks_up_msg_id_as_default_singular
- assert_equal 'A special apple', nsgettext('special|A special apple', '{{count}} special apples', 1, '|')
+ assert_equal 'A special apple', nsgettext('special|A special apple', '{{count}} special apples', 1)
+ assert_equal 'A special apple', ns_('special|A special apple', '{{count}} special apples', 1)
+ end
+
+ def test_nsgettext_looks_up_msg_id_plural_as_default_plural
+ assert_equal '2 special apples', nsgettext('special|A special apple', '{{count}} special apples', 2)
+ assert_equal '2 special apples', ns_('special|A special apple', '{{count}} special apples', 2)
+ end
+
+ def test_nsgettext_looks_up_a_singular
+ I18n.locale = :de
+ assert_equal 'Ein spezieller Apfel', nsgettext('special|A special apple', '{{count}} special apples', 1)
+ assert_equal 'Ein spezieller Apfel', ns_('special|A special apple', '{{count}} special apples', 1)
+ end
+
+ def test_nsgettext_looks_up_a_plural
+ I18n.locale = :de
+ assert_equal '2 spezielle Äpfel', nsgettext('special|A special apple', '{{count}} special apples', 2)
+ assert_equal '2 spezielle Äpfel', ns_('special|A special apple', '{{count}} special apples', 2)
+ end
+
+ def test_nsgettext_looks_up_msg_id_as_default_singular_with_alternative_syntax
+ assert_equal 'A special apple', nsgettext(['special|A special apple', '{{count}} special apples'], 1)
+ assert_equal 'A special apple', ns_(['special|A special apple', '{{count}} special apples'], 1)
+ end
+
+ def test_nsgettext_looks_up_msg_id_plural_as_default_plural_with_alternative_syntax
+ assert_equal '2 special apples', nsgettext(['special|A special apple', '{{count}} special apples'], 2)
+ assert_equal '2 special apples', ns_(['special|A special apple', '{{count}} special apples'], 2)
+ end
+
+ def test_nsgettext_looks_up_a_singular_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal 'Ein spezieller Apfel', nsgettext(['special|A special apple', '{{count}} special apples'], 1)
+ assert_equal 'Ein spezieller Apfel', ns_(['special|A special apple', '{{count}} special apples'], 1)
+ end
+
+ def test_nsgettext_looks_up_a_plural_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal '2 spezielle Äpfel', nsgettext(['special|A special apple', '{{count}} special apples'], 2)
+ assert_equal '2 spezielle Äpfel', ns_(['special|A special apple', '{{count}} special apples'], 2)
+ end
+
+ # npgettext
+ def test_npgettext_looks_up_msg_id_as_default_singular
+ assert_equal 'A special apple', npgettext('special', 'A special apple', '{{count}} special apples', 1)
+ assert_equal 'A special apple', np_('special', 'A special apple', '{{count}} special apples', 1)
+ end
+
+ def test_npgettext_looks_up_msg_id_plural_as_default_plural
+ assert_equal '2 special apples', npgettext('special', 'A special apple', '{{count}} special apples', 2)
+ assert_equal '2 special apples', np_('special', 'A special apple', '{{count}} special apples', 2)
+ end
+
+ def test_npgettext_looks_up_a_singular
+ I18n.locale = :de
+ assert_equal 'Ein spezieller Apfel', npgettext('special', 'A special apple', '{{count}} special apples', 1)
+ assert_equal 'Ein spezieller Apfel', np_('special', 'A special apple', '{{count}} special apples', 1)
+ end
+
+ def test_npgettext_looks_up_a_plural
+ I18n.locale = :de
+ assert_equal '2 spezielle Äpfel', npgettext('special', 'A special apple', '{{count}} special apples', 2)
+ assert_equal '2 spezielle Äpfel', np_('special', 'A special apple', '{{count}} special apples', 2)
+ end
+
+ def test_npgettext_looks_up_msg_id_as_default_singular_with_alternative_syntax
+ assert_equal 'A special apple', npgettext('special', ['A special apple', '{{count}} special apples'], 1)
+ assert_equal 'A special apple', np_('special', ['A special apple', '{{count}} special apples'], 1)
+ end
+
+ def test_npgettext_looks_up_msg_id_plural_as_default_plural_with_alternative_syntax
+ assert_equal '2 special apples', npgettext('special', ['A special apple', '{{count}} special apples'], 2)
+ assert_equal '2 special apples', np_('special', ['A special apple', '{{count}} special apples'], 2)
+ end
+
+ def test_npgettext_looks_up_a_singular_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal 'Ein spezieller Apfel', npgettext('special', ['A special apple', '{{count}} special apples'], 1)
+ assert_equal 'Ein spezieller Apfel', np_('special', ['A special apple', '{{count}} special apples'], 1)
+ end
+
+ def test_npgettext_looks_up_a_plural_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal '2 spezielle Äpfel', npgettext('special', ['A special apple', '{{count}} special apples'], 2)
+ assert_equal '2 spezielle Äpfel', np_('special', ['A special apple', '{{count}} special apples'], 2)
end
end
View
54 test/gettext/backend_test.rb
@@ -4,9 +4,9 @@
require 'i18n/backend/gettext'
require 'i18n/helpers/gettext'
-include I18n::Helpers::Gettext
-
class I18nGettextBackendTest < Test::Unit::TestCase
+ include I18n::Helpers::Gettext
+
class Backend
include I18n::Backend::Base
include I18n::Backend::Gettext
@@ -25,16 +25,60 @@ def teardown
def test_backend_loads_po_file
I18n.backend.send(:init_translations)
- assert I18n.backend.send(:translations)[:de][:"Axis\001Axis"]
+ assert I18n.backend.send(:translations)[:de][:"Axis"]
+ end
+
+ def test_looks_up_a_translation
+ I18n.locale = :de
+ assert_equal 'Auto', gettext('car')
end
- def test_looks_up_translation
+ def test_uses_default_translation
+ assert_equal 'car', gettext('car')
+ end
+
+ def test_looks_up_a_namespaced_translation
I18n.locale = :de
- assert_equal 'Auto', _('car')
+ assert_equal 'Räderzahl', sgettext('Car|Wheels count')
+ assert_equal 'Räderzahl', pgettext('Car', 'Wheels count')
+ end
+
+ def test_uses_namespaced_default_translation
+ assert_equal 'Wheels count', sgettext('Car|Wheels count')
+ assert_equal 'Wheels count', pgettext('Car', 'Wheels count')
end
def test_pluralizes_entry
I18n.locale = :de
+ assert_equal 'Achse', ngettext('Axis', 'Axis', 1)
assert_equal 'Achsen', ngettext('Axis', 'Axis', 2)
end
+
+ def test_pluralizes_default_entry
+ assert_equal 'Axis', ngettext('Axis', 'Axis', 1)
+ assert_equal 'Axis', ngettext('Axis', 'Axis', 2)
+ end
+
+ def test_pluralizes_namespaced_entry
+ I18n.locale = :de
+ assert_equal 'Rad', nsgettext('Car|wheel', 'wheels', 1)
+ assert_equal 'Räder', nsgettext('Car|wheel', 'wheels', 2)
+ assert_equal 'Rad', npgettext('Car', 'wheel', 'wheels', 1)
+ assert_equal 'Räder', npgettext('Car', 'wheel', 'wheels', 2)
+ end
+
+ def test_pluralizes_namespaced_default_entry
+ assert_equal 'wheel', nsgettext('Car|wheel', 'wheels', 1)
+ assert_equal 'wheels', nsgettext('Car|wheel', 'wheels', 2)
+ assert_equal 'wheel', npgettext('Car', 'wheel', 'wheels', 1)
+ assert_equal 'wheels', npgettext('Car', 'wheel', 'wheels', 2)
+ end
+
+ def test_pluralizes_namespaced_entry_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal 'Rad', nsgettext(['Car|wheel', 'wheels'], 1)
+ assert_equal 'Räder', nsgettext(['Car|wheel', 'wheels'], 2)
+ assert_equal 'Rad', npgettext('Car', ['wheel', 'wheels'], 1)
+ assert_equal 'Räder', npgettext('Car', ['wheel', 'wheels'], 2)
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.