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,119 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The InterpolationCompiler module contains optimizations that can tremendously
|
4
|
+
# speed up the interpolation process on the Simple backend.
|
5
|
+
#
|
6
|
+
# It works by defining a pre-compiled method on stored translation Strings that
|
7
|
+
# already bring all the knowledge about contained interpolation variables etc.
|
8
|
+
# so that the actual recurring interpolation will be very fast.
|
9
|
+
#
|
10
|
+
# To enable pre-compiled interpolations you can simply include the
|
11
|
+
# InterpolationCompiler module to the Simple backend:
|
12
|
+
#
|
13
|
+
# I18n::Backend::Simple.send(:include, I18n::Backend::InterpolationCompiler)
|
14
|
+
module I18n
|
15
|
+
module Backend
|
16
|
+
module InterpolationCompiler
|
17
|
+
module Compiler
|
18
|
+
extend self
|
19
|
+
|
20
|
+
TOKENIZER = /(\\\{\{[^\}]+\}\}|\{\{[^\}]+\}\})/
|
21
|
+
INTERPOLATION_SYNTAX_PATTERN = /(\\)?(\{\{([^\}]+)\}\})/
|
22
|
+
|
23
|
+
def compile_if_an_interpolation(string)
|
24
|
+
if interpolated_str?(string)
|
25
|
+
string.instance_eval <<-RUBY_EVAL, __FILE__, __LINE__
|
26
|
+
def i18n_interpolate(v = {})
|
27
|
+
"#{compiled_interpolation_body(string)}"
|
28
|
+
end
|
29
|
+
RUBY_EVAL
|
30
|
+
end
|
31
|
+
|
32
|
+
string
|
33
|
+
end
|
34
|
+
|
35
|
+
def interpolated_str?(str)
|
36
|
+
str.kind_of?(String) && str =~ INTERPOLATION_SYNTAX_PATTERN
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
# tokenize("foo {{bar}} baz \\{{buz}}") # => ["foo ", "{{bar}}", " baz ", "\\{{buz}}"]
|
41
|
+
def tokenize(str)
|
42
|
+
str.split(TOKENIZER)
|
43
|
+
end
|
44
|
+
|
45
|
+
def compiled_interpolation_body(str)
|
46
|
+
tokenize(str).map do |token|
|
47
|
+
(matchdata = token.match(INTERPOLATION_SYNTAX_PATTERN)) ? handle_interpolation_token(token, matchdata) : escape_plain_str(token)
|
48
|
+
end.join
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_interpolation_token(interpolation, matchdata)
|
52
|
+
escaped, pattern, key = matchdata.values_at(1, 2, 3)
|
53
|
+
escaped ? pattern : compile_interpolation_token(key.to_sym)
|
54
|
+
end
|
55
|
+
|
56
|
+
def compile_interpolation_token(key)
|
57
|
+
"\#{#{interpolate_or_raise_missing(key)}}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def interpolate_or_raise_missing(key)
|
61
|
+
escaped_key = escape_key_sym(key)
|
62
|
+
Base::RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key)
|
63
|
+
end
|
64
|
+
|
65
|
+
def interpolate_key(key)
|
66
|
+
[direct_key(key), nil_key(key), missing_key(key)].join('||')
|
67
|
+
end
|
68
|
+
|
69
|
+
def direct_key(key)
|
70
|
+
"((t = v[#{key}]) && t.respond_to?(:call) ? t.call : t)"
|
71
|
+
end
|
72
|
+
|
73
|
+
def nil_key(key)
|
74
|
+
"(v.has_key?(#{key}) && '')"
|
75
|
+
end
|
76
|
+
|
77
|
+
def missing_key(key)
|
78
|
+
"raise(MissingInterpolationArgument.new(#{key}, self))"
|
79
|
+
end
|
80
|
+
|
81
|
+
def reserved_key(key)
|
82
|
+
"raise(ReservedInterpolationKey.new(#{key}, self))"
|
83
|
+
end
|
84
|
+
|
85
|
+
def escape_plain_str(str)
|
86
|
+
str.gsub(/"|\\|#/) {|x| "\\#{x}"}
|
87
|
+
end
|
88
|
+
|
89
|
+
def escape_key_sym(key)
|
90
|
+
# rely on Ruby to do all the hard work :)
|
91
|
+
key.to_sym.inspect
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def interpolate(locale, string, values)
|
96
|
+
if string.respond_to?(:i18n_interpolate)
|
97
|
+
string.i18n_interpolate(values)
|
98
|
+
elsif values
|
99
|
+
super
|
100
|
+
else
|
101
|
+
string
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def merge_translations(locale, data)
|
106
|
+
compile_all_strings_in(data)
|
107
|
+
super
|
108
|
+
end
|
109
|
+
|
110
|
+
protected
|
111
|
+
def compile_all_strings_in(data)
|
112
|
+
data.each_value do |value|
|
113
|
+
Compiler.compile_if_an_interpolation(value)
|
114
|
+
compile_all_strings_in(value) if value.kind_of?(Hash)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# I18n translation metadata is useful when you want to access information
|
2
|
+
# about how a translation was looked up, pluralized or interpolated in
|
3
|
+
# your application.
|
4
|
+
#
|
5
|
+
# msg = I18n.t(:message, :default => 'Hi!', :scope => :foo)
|
6
|
+
# msg.translation_metadata
|
7
|
+
# # => { :key => :message, :scope => :foo, :default => 'Hi!' }
|
8
|
+
#
|
9
|
+
# If a :count option was passed to #translate it will be set to the metadata.
|
10
|
+
# Likewise, if any interpolation variables were passed they will also be set.
|
11
|
+
#
|
12
|
+
# To enable translation metadata you can simply include the Metadata module
|
13
|
+
# into the Simple backend class - or whatever other backend you are using:
|
14
|
+
#
|
15
|
+
# I18n::Backend::Simple.send(:include, I18n::Backend::Metadata)
|
16
|
+
|
17
|
+
require 'i18n/core_ext/object/meta_class'
|
18
|
+
|
19
|
+
module I18n
|
20
|
+
module Backend
|
21
|
+
module Metadata
|
22
|
+
class << self
|
23
|
+
def included(base)
|
24
|
+
Object.class_eval do
|
25
|
+
def translation_metadata
|
26
|
+
@translation_metadata ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def translation_metadata=(translation_metadata)
|
30
|
+
@translation_metadata = translation_metadata
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def translate(locale, key, options = {})
|
37
|
+
metadata = {
|
38
|
+
:locale => locale,
|
39
|
+
:key => key,
|
40
|
+
:scope => options[:scope],
|
41
|
+
:default => options[:default],
|
42
|
+
:separator => options[:separator],
|
43
|
+
:values => options.reject { |name, value| Base::RESERVED_KEYS.include?(name) }
|
44
|
+
}
|
45
|
+
with_metadata(metadata) { super }
|
46
|
+
end
|
47
|
+
|
48
|
+
def interpolate(locale, string, values = {})
|
49
|
+
with_metadata(:original => string) do
|
50
|
+
preserve_translation_metadata(string) { super }
|
51
|
+
end if string
|
52
|
+
end
|
53
|
+
|
54
|
+
def pluralize(locale, entry, count)
|
55
|
+
with_metadata(:count => count) { super }
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def with_metadata(metadata, &block)
|
61
|
+
result = yield
|
62
|
+
result.translation_metadata = result.translation_metadata.merge(metadata) if result
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
def preserve_translation_metadata(object, &block)
|
67
|
+
result = yield
|
68
|
+
result.translation_metadata = object.translation_metadata if result
|
69
|
+
result
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# I18n locale fallbacks are useful when you want your application to use
|
4
|
+
# translations from other locales when translations for the current locale are
|
5
|
+
# missing. E.g. you might want to use :en translations when translations in
|
6
|
+
# your applications main locale :de are missing.
|
7
|
+
#
|
8
|
+
# To enable locale specific pluralizations you can simply include the
|
9
|
+
# Pluralization module to the Simple backend - or whatever other backend you
|
10
|
+
# are using.
|
11
|
+
#
|
12
|
+
# I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
13
|
+
#
|
14
|
+
# You also need to make sure to provide pluralization algorithms to the
|
15
|
+
# backend, i.e. include them to your I18n.load_path accordingly.
|
16
|
+
module I18n
|
17
|
+
module Backend
|
18
|
+
module Pluralization
|
19
|
+
# Overwrites the Base backend translate method so that it will check the
|
20
|
+
# translation meta data space (:i18n) for a locale specific pluralization
|
21
|
+
# rule and use it to pluralize the given entry. I.e. the library expects
|
22
|
+
# pluralization rules to be stored at I18n.t(:'i18n.plural.rule')
|
23
|
+
#
|
24
|
+
# Pluralization rules are expected to respond to #call(entry, count) and
|
25
|
+
# return a pluralization key. Valid keys depend on the translation data
|
26
|
+
# hash (entry) but it is generally recommended to follow CLDR's style,
|
27
|
+
# i.e., return one of the keys :zero, :one, :few, :many, :other.
|
28
|
+
#
|
29
|
+
# The :zero key is always picked directly when count equals 0 AND the
|
30
|
+
# translation data has the key :zero. This way translators are free to
|
31
|
+
# either pick a special :zero translation even for languages where the
|
32
|
+
# pluralizer does not return a :zero key.
|
33
|
+
def pluralize(locale, entry, count)
|
34
|
+
return entry unless entry.is_a?(Hash) and count
|
35
|
+
|
36
|
+
pluralizer = pluralizer(locale)
|
37
|
+
if pluralizer.respond_to?(:call)
|
38
|
+
key = count == 0 && entry.has_key?(:zero) ? :zero : pluralizer.call(count)
|
39
|
+
raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key)
|
40
|
+
entry[key]
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def pluralizers
|
49
|
+
@pluralizers ||= {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def pluralizer(locale)
|
53
|
+
pluralizers[locale] ||= lookup(locale, :'i18n.plural.rule')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Stub class for the Simple backend. The actual implementation is provided by
|
4
|
+
# the backend Base class. This makes it easier to extend the Simple backend's
|
5
|
+
# behaviour by including modules. E.g.:
|
6
|
+
#
|
7
|
+
# module I18n::Backend::Pluralization
|
8
|
+
# def pluralize(*args)
|
9
|
+
# # extended pluralization logic
|
10
|
+
# super
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
15
|
+
|
16
|
+
module I18n
|
17
|
+
module Backend
|
18
|
+
class Simple
|
19
|
+
include Base
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
heavily based on Masao Mutoh's gettext String interpolation extension
|
5
|
+
http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
|
6
|
+
Copyright (C) 2005-2009 Masao Mutoh
|
7
|
+
You may redistribute it and/or modify it under the same license terms as Ruby.
|
8
|
+
=end
|
9
|
+
|
10
|
+
if RUBY_VERSION < '1.9'
|
11
|
+
|
12
|
+
# KeyError is raised by String#% when the string contains a named placeholder
|
13
|
+
# that is not contained in the given arguments hash. Ruby 1.9 includes and
|
14
|
+
# raises this exception natively. We define it to mimic Ruby 1.9's behaviour
|
15
|
+
# in Ruby 1.8.x
|
16
|
+
|
17
|
+
class KeyError < IndexError
|
18
|
+
def initialize(message = nil)
|
19
|
+
super(message || "key not found")
|
20
|
+
end
|
21
|
+
end unless defined?(KeyError)
|
22
|
+
|
23
|
+
# Extension for String class. This feature is included in Ruby 1.9 or later but not occur TypeError.
|
24
|
+
#
|
25
|
+
# String#% method which accept "named argument". The translator can know
|
26
|
+
# the meaning of the msgids using "named argument" instead of %s/%d style.
|
27
|
+
|
28
|
+
class String
|
29
|
+
# For older ruby versions, such as ruby-1.8.5
|
30
|
+
alias :bytesize :size unless instance_methods.find {|m| m.to_s == 'bytesize'}
|
31
|
+
alias :interpolate_without_ruby_19_syntax :% # :nodoc:
|
32
|
+
|
33
|
+
INTERPOLATION_PATTERN = Regexp.union(
|
34
|
+
/%\{(\w+)\}/, # matches placeholders like "%{foo}"
|
35
|
+
/%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
|
36
|
+
)
|
37
|
+
|
38
|
+
INTERPOLATION_PATTERN_WITH_ESCAPE = Regexp.union(
|
39
|
+
/%%/,
|
40
|
+
INTERPOLATION_PATTERN
|
41
|
+
)
|
42
|
+
|
43
|
+
# % uses self (i.e. the String) as a format specification and returns the
|
44
|
+
# result of applying it to the given arguments. In other words it interpolates
|
45
|
+
# the given arguments to the string according to the formats the string
|
46
|
+
# defines.
|
47
|
+
#
|
48
|
+
# There are three ways to use it:
|
49
|
+
#
|
50
|
+
# * Using a single argument or Array of arguments.
|
51
|
+
#
|
52
|
+
# This is the default behaviour of the String class. See Kernel#sprintf for
|
53
|
+
# more details about the format string.
|
54
|
+
#
|
55
|
+
# Example:
|
56
|
+
#
|
57
|
+
# "%d %s" % [1, "message"]
|
58
|
+
# # => "1 message"
|
59
|
+
#
|
60
|
+
# * Using a Hash as an argument and unformatted, named placeholders.
|
61
|
+
#
|
62
|
+
# When you pass a Hash as an argument and specify placeholders with %{foo}
|
63
|
+
# it will interpret the hash values as named arguments.
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
#
|
67
|
+
# "%{firstname}, %{lastname}" % {:firstname => "Masao", :lastname => "Mutoh"}
|
68
|
+
# # => "Masao Mutoh"
|
69
|
+
#
|
70
|
+
# * Using a Hash as an argument and formatted, named placeholders.
|
71
|
+
#
|
72
|
+
# When you pass a Hash as an argument and specify placeholders with %<foo>d
|
73
|
+
# it will interpret the hash values as named arguments and format the value
|
74
|
+
# according to the formatting instruction appended to the closing >.
|
75
|
+
#
|
76
|
+
# Example:
|
77
|
+
#
|
78
|
+
# "%<integer>d, %<float>.1f" % { :integer => 10, :float => 43.4 }
|
79
|
+
# # => "10, 43.3"
|
80
|
+
def %(args)
|
81
|
+
if args.kind_of?(Hash)
|
82
|
+
dup.gsub(INTERPOLATION_PATTERN_WITH_ESCAPE) do |match|
|
83
|
+
if match == '%%'
|
84
|
+
'%'
|
85
|
+
else
|
86
|
+
key = ($1 || $2).to_sym
|
87
|
+
raise KeyError unless args.has_key?(key)
|
88
|
+
$3 ? sprintf("%#{$3}", args[key]) : args[key]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
elsif self =~ INTERPOLATION_PATTERN
|
92
|
+
raise ArgumentError.new('one hash required')
|
93
|
+
else
|
94
|
+
result = gsub(/%([{<])/, '%%\1')
|
95
|
+
result.send :'interpolate_without_ruby_19_syntax', args
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -1,3 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class KeyError < IndexError
|
4
|
+
def initialize(message = nil)
|
5
|
+
super(message || "key not found")
|
6
|
+
end
|
7
|
+
end unless defined?(KeyError)
|
8
|
+
|
1
9
|
module I18n
|
2
10
|
class ArgumentError < ::ArgumentError; end
|
3
11
|
|
@@ -11,8 +19,8 @@ module I18n
|
|
11
19
|
|
12
20
|
class MissingTranslationData < ArgumentError
|
13
21
|
attr_reader :locale, :key, :options
|
14
|
-
def initialize(locale, key,
|
15
|
-
@key, @locale, @options = key, locale,
|
22
|
+
def initialize(locale, key, opts = nil)
|
23
|
+
@key, @locale, @options = key, locale, opts || {}
|
16
24
|
keys = I18n.send(:normalize_translation_keys, locale, key, options[:scope])
|
17
25
|
keys << 'no key' if keys.size < 2
|
18
26
|
super "translation missing: #{keys.join(', ')}"
|
@@ -28,10 +36,10 @@ module I18n
|
|
28
36
|
end
|
29
37
|
|
30
38
|
class MissingInterpolationArgument < ArgumentError
|
31
|
-
attr_reader :
|
32
|
-
def initialize(
|
33
|
-
@
|
34
|
-
super "interpolation argument #{
|
39
|
+
attr_reader :values, :string
|
40
|
+
def initialize(values, string)
|
41
|
+
@values, @string = values, string
|
42
|
+
super "missing interpolation argument in #{string.inspect} (#{values.inspect} given)"
|
35
43
|
end
|
36
44
|
end
|
37
45
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Gettext
|
5
|
+
PLURAL_SEPARATOR = "\001"
|
6
|
+
CONTEXT_SEPARATOR = "\004"
|
7
|
+
|
8
|
+
@@plural_keys = { :en => [:one, :other] }
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# returns an array of plural keys for the given locale so that we can
|
12
|
+
# convert from gettext's integer-index based style
|
13
|
+
# TODO move this information to the pluralization module
|
14
|
+
def plural_keys(locale)
|
15
|
+
@@plural_keys[locale] || @@plural_keys[:en]
|
16
|
+
end
|
17
|
+
|
18
|
+
def extract_scope(msgid, separator)
|
19
|
+
scope = msgid.to_s.split(separator)
|
20
|
+
msgid = scope.pop
|
21
|
+
[scope, msgid]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|