activesupport 2.3.5 → 2.3.6.pre
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- data/CHANGELOG +23 -0
- data/lib/active_support.rb +1 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +14 -3
- data/lib/active_support/core_ext/enumerable.rb +6 -0
- data/lib/active_support/core_ext/file/atomic.rb +2 -1
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -2
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/object/metaclass.rb +6 -5
- data/lib/active_support/core_ext/object/singleton_class.rb +13 -0
- data/lib/active_support/core_ext/string.rb +0 -1
- data/lib/active_support/core_ext/string/output_safety.rb +148 -44
- data/lib/active_support/core_ext/time/calculations.rb +1 -1
- data/lib/active_support/inflector.rb +1 -1
- data/lib/active_support/json/backends/yajl.rb +40 -0
- data/lib/active_support/json/decoding.rb +16 -1
- data/lib/active_support/json/encoding.rb +11 -2
- data/lib/active_support/ordered_hash.rb +24 -1
- data/lib/active_support/vendor.rb +10 -2
- data/lib/active_support/vendor/i18n-0.3.3/CHANGELOG.textile +76 -0
- data/lib/active_support/vendor/{i18n-0.1.3 → i18n-0.3.3}/MIT-LICENSE +0 -0
- data/lib/active_support/vendor/i18n-0.3.3/README.textile +81 -0
- data/lib/active_support/vendor/i18n-0.3.3/Rakefile +24 -0
- data/lib/active_support/vendor/i18n-0.3.3/benchmark/example.yml +144 -0
- data/lib/active_support/vendor/i18n-0.3.3/benchmark/run.rb +71 -0
- data/lib/active_support/vendor/i18n-0.3.3/contributors.txt +17 -0
- data/lib/active_support/vendor/i18n-0.3.3/i18n.gemspec +165 -0
- data/lib/active_support/vendor/i18n-0.3.3/init.rb +1 -0
- data/lib/active_support/vendor/{i18n-0.1.3 → i18n-0.3.3}/lib/i18n.rb +99 -21
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend.rb +17 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record.rb +70 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record/missing.rb +67 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record/store_procs.rb +38 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record/translation.rb +83 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/base.rb +259 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/cache.rb +75 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/cascade.rb +44 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/chain.rb +74 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/fallbacks.rb +52 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/fast.rb +68 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/gettext.rb +75 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/helpers.rb +80 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/interpolation_compiler.rb +119 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/metadata.rb +73 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/pluralization.rb +57 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/simple.rb +22 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/core_ext/object/meta_class.rb +5 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/core_ext/string/interpolate.rb +99 -0
- data/lib/active_support/vendor/{i18n-0.1.3 → i18n-0.3.3}/lib/i18n/exceptions.rb +14 -6
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/gettext.rb +25 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/helpers.rb +5 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/helpers/gettext.rb +64 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale.rb +6 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/fallbacks.rb +98 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag.rb +28 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag/parents.rb +24 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag/rfc4646.rb +76 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag/simple.rb +41 -0
- data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/version.rb +3 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/all.rb +8 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/basics.rb +15 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/defaults.rb +40 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/interpolation.rb +92 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/link.rb +55 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/date.rb +91 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/date_time.rb +90 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/procs.rb +54 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/time.rb +84 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/lookup.rb +45 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/pluralization.rb +35 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/api/procs.rb +40 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/active_record_test.rb +29 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/all_features_test.rb +40 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/cascade_test.rb +31 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/chain_test.rb +26 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/fallbacks_test.rb +33 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/fast_test.rb +31 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/pluralization_test.rb +33 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/simple_test.rb +21 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/active_record/missing_test.rb +60 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/active_record_test.rb +52 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/cache_test.rb +72 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/cascade_test.rb +66 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/chain_test.rb +64 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/fallbacks_test.rb +57 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/fast_test.rb +50 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/helpers_test.rb +26 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/interpolation_compiler_test.rb +107 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/metadata_test.rb +67 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/pluralization_test.rb +43 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/simple_test.rb +77 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/core_ext/string/interpolate_test.rb +94 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/gettext/api_test.rb +201 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/gettext/backend_test.rb +91 -0
- data/lib/active_support/vendor/{i18n-0.1.3/test → i18n-0.3.3/test/cases}/i18n_exceptions_test.rb +8 -10
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/i18n_load_path_test.rb +23 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/i18n_test.rb +172 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/locale/fallbacks_test.rb +126 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/locale/tag/rfc4646_test.rb +143 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/cases/locale/tag/simple_test.rb +33 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/de.po +72 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/en.rb +3 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/en.yml +3 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/plurals.rb +113 -0
- data/lib/active_support/vendor/i18n-0.3.3/test/test_helper.rb +100 -0
- data/lib/active_support/vendor/i18n-0.3.3/vendor/po_parser.rb +329 -0
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/whiny_nil.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +23 -83
- data/lib/active_support/xml_mini/libxmlsax.rb +74 -0
- data/lib/active_support/xml_mini/nokogiri.rb +25 -22
- data/lib/active_support/xml_mini/nokogirisax.rb +73 -0
- metadata +108 -20
- data/lib/active_support/vendor/i18n-0.1.3/README.textile +0 -20
- data/lib/active_support/vendor/i18n-0.1.3/Rakefile +0 -5
- data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +0 -27
- data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb +0 -214
- data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +0 -5
- data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +0 -124
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +0 -1
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +0 -3
- data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +0 -567
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Helpers
|
5
|
+
# Implements classical Gettext style accessors. To use this include the
|
6
|
+
# module to the global namespace or wherever you want to use it.
|
7
|
+
#
|
8
|
+
# include I18n::Helpers::Gettext
|
9
|
+
module Gettext
|
10
|
+
def gettext(msgid, options = {})
|
11
|
+
I18n.t(msgid, { :default => msgid, :separator => '|' }.merge(options))
|
12
|
+
end
|
13
|
+
alias _ gettext
|
14
|
+
|
15
|
+
def sgettext(msgid, separator = '|')
|
16
|
+
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
|
17
|
+
I18n.t(msgid, :scope => scope, :default => msgid)
|
18
|
+
end
|
19
|
+
alias s_ sgettext
|
20
|
+
|
21
|
+
def pgettext(msgctxt, msgid)
|
22
|
+
separator = I18n::Gettext::CONTEXT_SEPARATOR
|
23
|
+
sgettext([msgctxt, msgid].join(separator), separator)
|
24
|
+
end
|
25
|
+
alias p_ pgettext
|
26
|
+
|
27
|
+
def ngettext(msgid, msgid_plural, n = 1)
|
28
|
+
nsgettext(msgid, msgid_plural, n)
|
29
|
+
end
|
30
|
+
alias n_ ngettext
|
31
|
+
|
32
|
+
# Method signatures:
|
33
|
+
# nsgettext('Fruits|apple', 'apples', 2)
|
34
|
+
# nsgettext(['Fruits|apple', 'apples'], 2)
|
35
|
+
def nsgettext(msgid, msgid_plural, n = 1, separator = '|')
|
36
|
+
if msgid.is_a?(Array)
|
37
|
+
msgid, msgid_plural, n, separator = msgid[0], msgid[1], msgid_plural, n
|
38
|
+
separator = '|' unless separator.is_a?(String)
|
39
|
+
end
|
40
|
+
|
41
|
+
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
|
42
|
+
default = { :one => msgid, :other => msgid_plural }
|
43
|
+
I18n.t(msgid, :default => default, :count => n, :scope => scope, :separator => separator)
|
44
|
+
end
|
45
|
+
alias ns_ nsgettext
|
46
|
+
|
47
|
+
# Method signatures:
|
48
|
+
# npgettext('Fruits', 'apple', 'apples', 2)
|
49
|
+
# npgettext('Fruits', ['apple', 'apples'], 2)
|
50
|
+
def npgettext(msgctxt, msgid, msgid_plural, n = 1)
|
51
|
+
separator = I18n::Gettext::CONTEXT_SEPARATOR
|
52
|
+
|
53
|
+
if msgid.is_a?(Array)
|
54
|
+
msgid_plural, msgid, n = msgid[1], [msgctxt, msgid[0]].join(separator), msgid_plural
|
55
|
+
else
|
56
|
+
msgid = [msgctxt, msgid].join(separator)
|
57
|
+
end
|
58
|
+
|
59
|
+
nsgettext(msgid, msgid_plural, n, separator)
|
60
|
+
end
|
61
|
+
alias np_ npgettext
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Locale Fallbacks
|
4
|
+
#
|
5
|
+
# Extends the I18n module to hold a fallbacks instance which is set to an
|
6
|
+
# instance of I18n::Locale::Fallbacks by default but can be swapped with a
|
7
|
+
# different implementation.
|
8
|
+
#
|
9
|
+
# Locale fallbacks will compute a number of fallback locales for a given locale.
|
10
|
+
# For example:
|
11
|
+
#
|
12
|
+
# <pre><code>
|
13
|
+
# I18n.fallbacks[:"es-MX"] # => [:"es-MX", :es, :en] </code></pre>
|
14
|
+
#
|
15
|
+
# Locale fallbacks always fall back to
|
16
|
+
#
|
17
|
+
# * all parent locales of a given locale (e.g. :es for :"es-MX") first,
|
18
|
+
# * the current default locales and all of their parents second
|
19
|
+
#
|
20
|
+
# The default locales are set to [I18n.default_locale] by default but can be
|
21
|
+
# set to something else.
|
22
|
+
#
|
23
|
+
# One can additionally add any number of additional fallback locales manually.
|
24
|
+
# These will be added before the default locales to the fallback chain. For
|
25
|
+
# example:
|
26
|
+
#
|
27
|
+
# # using the default locale as default fallback locale
|
28
|
+
#
|
29
|
+
# I18n.default_locale = :"en-US"
|
30
|
+
# I18n.fallbacks = I18n::Fallbacks.new(:"de-AT" => :"de-DE")
|
31
|
+
# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :"de-DE", :de, :"en-US", :en]
|
32
|
+
#
|
33
|
+
# # using a custom locale as default fallback locale
|
34
|
+
#
|
35
|
+
# I18n.fallbacks = I18n::Fallbacks.new(:"en-GB", :"de-AT" => :de, :"de-CH" => :de)
|
36
|
+
# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :de, :"en-GB", :en]
|
37
|
+
# I18n.fallbacks[:"de-CH"] # => [:"de-CH", :de, :"en-GB", :en]
|
38
|
+
#
|
39
|
+
# # mapping fallbacks to an existing instance
|
40
|
+
#
|
41
|
+
# # people speaking Catalan also speak Spanish as spoken in Spain
|
42
|
+
# fallbacks = I18n.fallbacks
|
43
|
+
# fallbacks.map(:ca => :"es-ES")
|
44
|
+
# fallbacks[:ca] # => [:ca, :"es-ES", :es, :"en-US", :en]
|
45
|
+
#
|
46
|
+
# # people speaking Arabian as spoken in Palestine also speak Hebrew as spoken in Israel
|
47
|
+
# fallbacks.map(:"ar-PS" => :"he-IL")
|
48
|
+
# fallbacks[:"ar-PS"] # => [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en]
|
49
|
+
# fallbacks[:"ar-EG"] # => [:"ar-EG", :ar, :"en-US", :en]
|
50
|
+
#
|
51
|
+
# # people speaking Sami as spoken in Finnland also speak Swedish and Finnish as spoken in Finnland
|
52
|
+
# fallbacks.map(:sms => [:"se-FI", :"fi-FI"])
|
53
|
+
# fallbacks[:sms] # => [:sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en]
|
54
|
+
|
55
|
+
module I18n
|
56
|
+
module Locale
|
57
|
+
class Fallbacks < Hash
|
58
|
+
def initialize(*mappings)
|
59
|
+
@map = {}
|
60
|
+
map(mappings.pop) if mappings.last.is_a?(Hash)
|
61
|
+
self.defaults = mappings.empty? ? [I18n.default_locale.to_sym] : mappings
|
62
|
+
end
|
63
|
+
|
64
|
+
def defaults=(defaults)
|
65
|
+
@defaults = defaults.map { |default| compute(default, false) }.flatten
|
66
|
+
end
|
67
|
+
attr_reader :defaults
|
68
|
+
|
69
|
+
def [](locale)
|
70
|
+
raise InvalidLocale.new(locale) if locale.nil?
|
71
|
+
locale = locale.to_sym
|
72
|
+
super || store(locale, compute(locale))
|
73
|
+
end
|
74
|
+
|
75
|
+
def map(mappings)
|
76
|
+
mappings.each do |from, to|
|
77
|
+
from, to = from.to_sym, Array(to)
|
78
|
+
to.each do |to|
|
79
|
+
@map[from] ||= []
|
80
|
+
@map[from] << to.to_sym
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
def compute(tags, include_defaults = true)
|
88
|
+
result = Array(tags).collect do |tag|
|
89
|
+
tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym }
|
90
|
+
tags.each { |tag| tags += compute(@map[tag]) if @map[tag] }
|
91
|
+
tags
|
92
|
+
end.flatten
|
93
|
+
result.push(*defaults) if include_defaults
|
94
|
+
result.uniq
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Locale
|
5
|
+
module Tag
|
6
|
+
autoload :Parents, 'i18n/locale/tag/parents'
|
7
|
+
autoload :Rfc4646, 'i18n/locale/tag/rfc4646'
|
8
|
+
autoload :Simple, 'i18n/locale/tag/simple'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# Returns the current locale tag implementation. Defaults to +I18n::Locale::Tag::Simple+.
|
12
|
+
def implementation
|
13
|
+
@@implementation ||= Simple
|
14
|
+
end
|
15
|
+
|
16
|
+
# Sets the current locale tag implementation. Use this to set a different locale tag implementation.
|
17
|
+
def implementation=(implementation)
|
18
|
+
@@implementation = implementation
|
19
|
+
end
|
20
|
+
|
21
|
+
# Factory method for locale tags. Delegates to the current locale tag implementation.
|
22
|
+
def tag(tag)
|
23
|
+
implementation.tag(tag)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Locale
|
5
|
+
module Tag
|
6
|
+
module Parents
|
7
|
+
def parent
|
8
|
+
@parent ||= begin
|
9
|
+
segs = to_a.compact
|
10
|
+
segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self_and_parents
|
15
|
+
@self_and_parents ||= [self] + parents
|
16
|
+
end
|
17
|
+
|
18
|
+
def parents
|
19
|
+
@parents ||= ([parent] + (parent ? parent.parents : [])).compact
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# RFC 4646/47 compliant Locale tag implementation that parses locale tags to
|
4
|
+
# subtags such as language, script, region, variant etc.
|
5
|
+
#
|
6
|
+
# For more information see by http://en.wikipedia.org/wiki/IETF_language_tag
|
7
|
+
#
|
8
|
+
# Rfc4646::Parser does not implement grandfathered tags.
|
9
|
+
|
10
|
+
module I18n
|
11
|
+
module Locale
|
12
|
+
module Tag
|
13
|
+
RFC4646_SUBTAGS = [ :language, :script, :region, :variant, :extension, :privateuse, :grandfathered ]
|
14
|
+
RFC4646_FORMATS = { :language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase }
|
15
|
+
|
16
|
+
class Rfc4646 < Struct.new(*RFC4646_SUBTAGS)
|
17
|
+
class << self
|
18
|
+
# Parses the given tag and returns a Tag instance if it is valid.
|
19
|
+
# Returns false if the given tag is not valid according to RFC 4646.
|
20
|
+
def tag(tag)
|
21
|
+
matches = parser.match(tag)
|
22
|
+
new(*matches) if matches
|
23
|
+
end
|
24
|
+
|
25
|
+
def parser
|
26
|
+
@@parser ||= Rfc4646::Parser
|
27
|
+
end
|
28
|
+
|
29
|
+
def parser=(parser)
|
30
|
+
@@parser = parser
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
include Parents
|
35
|
+
|
36
|
+
RFC4646_FORMATS.each do |name, format|
|
37
|
+
define_method(name) { self[name].send(format) unless self[name].nil? }
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_sym
|
41
|
+
to_s.to_sym
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
@tag ||= to_a.compact.join("-")
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_a
|
49
|
+
members.collect { |attr| self.send(attr) }
|
50
|
+
end
|
51
|
+
|
52
|
+
module Parser
|
53
|
+
PATTERN = %r{\A(?:
|
54
|
+
([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language
|
55
|
+
(?:-([a-z]{4}))? # script
|
56
|
+
(?:-([a-z]{2}|\d{3}))? # region
|
57
|
+
(?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))* # variant
|
58
|
+
(?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))* # extension
|
59
|
+
(?:-(x(?:-[0-9a-z]{1,8})+))?| # privateuse subtag
|
60
|
+
(x(?:-[0-9a-z]{1,8})+)| # privateuse tag
|
61
|
+
/* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */ # grandfathered
|
62
|
+
)\z}xi
|
63
|
+
|
64
|
+
class << self
|
65
|
+
def match(tag)
|
66
|
+
c = PATTERN.match(tag.to_s).captures
|
67
|
+
c[0..4] << (c[5].nil? ? c[6] : c[5]) << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here?
|
68
|
+
rescue
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Simple Locale tag implementation that computes subtags by simply splitting
|
4
|
+
# the locale tag at '-' occurences.
|
5
|
+
module I18n
|
6
|
+
module Locale
|
7
|
+
module Tag
|
8
|
+
class Simple
|
9
|
+
class << self
|
10
|
+
def tag(tag)
|
11
|
+
new(tag)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
include Parents
|
16
|
+
|
17
|
+
attr_reader :tag
|
18
|
+
|
19
|
+
def initialize(*tag)
|
20
|
+
@tag = tag.join('-').to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
def subtags
|
24
|
+
@subtags = tag.to_s.split('-').map { |subtag| subtag.to_s }
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_sym
|
28
|
+
tag
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
tag.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_a
|
36
|
+
subtags
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Tests
|
4
|
+
module Api
|
5
|
+
module Basics
|
6
|
+
def test_available_locales
|
7
|
+
store_translations('de', :foo => 'bar')
|
8
|
+
store_translations('en', :foo => 'foo')
|
9
|
+
|
10
|
+
assert I18n.available_locales.include?(:de)
|
11
|
+
assert I18n.available_locales.include?(:en)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Tests
|
4
|
+
module Api
|
5
|
+
module Defaults
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
store_translations(:foo => { :bar => 'bar', :baz => 'baz' })
|
9
|
+
end
|
10
|
+
|
11
|
+
define_method "test defaults: given nil as a key it returns the given default" do
|
12
|
+
assert_equal 'default', I18n.t(nil, :default => 'default')
|
13
|
+
end
|
14
|
+
|
15
|
+
define_method "test defaults: given a symbol as a default it translates the symbol" do
|
16
|
+
assert_equal 'bar', I18n.t(nil, :default => :'foo.bar')
|
17
|
+
end
|
18
|
+
|
19
|
+
define_method "test defaults: given a symbol as a default and a scope it stays inside the scope when looking up the symbol" do
|
20
|
+
assert_equal 'bar', I18n.t(:missing, :default => :bar, :scope => :foo)
|
21
|
+
end
|
22
|
+
|
23
|
+
define_method "test defaults: given an array as a default it returns the first match" do
|
24
|
+
assert_equal 'bar', I18n.t(:does_not_exist, :default => [:does_not_exist_2, :'foo.bar'])
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method "test defaults: given an array of missing keys it raises a MissingTranslationData exception" do
|
28
|
+
assert_raises I18n::MissingTranslationData do
|
29
|
+
I18n.t(:does_not_exist, :default => [:does_not_exist_2, :does_not_exist_3], :raise => true)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
define_method "test defaults: using a custom scope separator" do
|
34
|
+
# data must have been stored using the custom separator when using the ActiveRecord backend
|
35
|
+
I18n.backend.store_translations(:en, { :foo => { :bar => 'bar' } }, { :separator => '|' })
|
36
|
+
assert_equal 'bar', I18n.t(nil, :default => :'foo|bar', :separator => '|')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Tests
|
4
|
+
module Api
|
5
|
+
module Interpolation
|
6
|
+
def interpolate(*args)
|
7
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
8
|
+
key = args.pop
|
9
|
+
I18n.backend.translate('en', key, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
define_method "test interpolation: given no values it does not alter the string" do
|
13
|
+
assert_equal 'Hi {{name}}!', interpolate(:default => 'Hi {{name}}!')
|
14
|
+
end
|
15
|
+
|
16
|
+
define_method "test interpolation: given values it interpolates them into the string" do
|
17
|
+
assert_equal 'Hi David!', interpolate(:default => 'Hi {{name}}!', :name => 'David')
|
18
|
+
end
|
19
|
+
|
20
|
+
define_method "test interpolation: given a nil value it still interpolates it into the string" do
|
21
|
+
assert_equal 'Hi !', interpolate(:default => 'Hi {{name}}!', :name => nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
define_method "test interpolation: given a lambda as a value it calls it if the string contains the key" do
|
25
|
+
assert_equal 'Hi David!', interpolate(:default => 'Hi {{name}}!', :name => lambda { |*args| 'David' })
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method "test interpolation: given a lambda as a value it does not call it if the string does not contain the key" do
|
29
|
+
assert_nothing_raised { interpolate(:default => 'Hi!', :name => lambda { |*args| raise 'fail' }) }
|
30
|
+
end
|
31
|
+
|
32
|
+
define_method "test interpolation: given values but missing a key it raises I18n::MissingInterpolationArgument" do
|
33
|
+
assert_raises(I18n::MissingInterpolationArgument) do
|
34
|
+
interpolate(:default => '{{foo}}', :bar => 'bar')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
define_method "test interpolation: it does not raise I18n::MissingInterpolationArgument for escaped variables" do
|
39
|
+
assert_nothing_raised(I18n::MissingInterpolationArgument) do
|
40
|
+
assert_equal 'Barr {{foo}}', interpolate(:default => '{{bar}} \{{foo}}', :bar => 'Barr')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
define_method "test interpolation: it does not change the original, stored translation string" do
|
45
|
+
I18n.backend.store_translations(:en, :interpolate => 'Hi {{name}}!')
|
46
|
+
assert_equal 'Hi David!', interpolate(:interpolate, :name => 'David')
|
47
|
+
assert_equal 'Hi Yehuda!', interpolate(:interpolate, :name => 'Yehuda')
|
48
|
+
end
|
49
|
+
|
50
|
+
define_method "test interpolation: works with Ruby 1.9 syntax" do
|
51
|
+
assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => 'David')
|
52
|
+
end
|
53
|
+
|
54
|
+
define_method "test interpolation: given the translation is in utf-8 it still works" do
|
55
|
+
assert_equal 'Häi David!', interpolate(:default => 'Häi {{name}}!', :name => 'David')
|
56
|
+
end
|
57
|
+
|
58
|
+
define_method "test interpolation: given the value is in utf-8 it still works" do
|
59
|
+
assert_equal 'Hi ゆきひろ!', interpolate(:default => 'Hi {{name}}!', :name => 'ゆきひろ')
|
60
|
+
end
|
61
|
+
|
62
|
+
define_method "test interpolation: given the translation and the value are in utf-8 it still works" do
|
63
|
+
assert_equal 'こんにちは、ゆきひろさん!', interpolate(:default => 'こんにちは、{{name}}さん!', :name => 'ゆきひろ')
|
64
|
+
end
|
65
|
+
|
66
|
+
if Kernel.const_defined?(:Encoding)
|
67
|
+
define_method "test interpolation: given a euc-jp translation and a utf-8 value it raises Encoding::CompatibilityError" do
|
68
|
+
assert_raises(Encoding::CompatibilityError) do
|
69
|
+
interpolate(:default => euc_jp('こんにちは、{{name}}さん!'), :name => 'ゆきひろ')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# define_method "test interpolation: given a utf-8 translation and a euc-jp value it returns a translation in euc-jp" do
|
74
|
+
# assert_equal euc_jp('Hi ゆきひろ!'), interpolate(:default => 'Hi {{name}}!', :name => euc_jp('ゆきひろ'))
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# TODO should better explain how this relates to the test above with the simpler utf-8 default string
|
78
|
+
define_method "test interpolation: given a utf-8 translation and a euc-jp value it raises Encoding::CompatibilityError" do
|
79
|
+
assert_raises(Encoding::CompatibilityError) do
|
80
|
+
interpolate(:default => 'こんにちは、{{name}}さん!', :name => euc_jp('ゆきひろ'))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
define_method "test interpolation: given a translations containing a reserved key it raises I18n::ReservedInterpolationKey" do
|
86
|
+
assert_raises(I18n::ReservedInterpolationKey) { interpolate(:default => '{{default}}', :foo => :bar) }
|
87
|
+
assert_raises(I18n::ReservedInterpolationKey) { interpolate(:default => '{{scope}}', :foo => :bar) }
|
88
|
+
assert_raises(I18n::ReservedInterpolationKey) { interpolate(:default => '{{separator}}', :foo => :bar) }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|