r18n-core 0.3.2 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +11 -0
- data/README.rdoc +225 -53
- data/lib/r18n-core/filters.rb +34 -34
- data/lib/r18n-core/i18n.rb +110 -46
- data/lib/r18n-core/locale.rb +109 -103
- data/lib/r18n-core/translated.rb +9 -4
- data/lib/r18n-core/translated_string.rb +10 -0
- data/lib/r18n-core/translation.rb +55 -99
- data/lib/r18n-core/unsupported_locale.rb +1 -13
- data/lib/r18n-core/untranslated.rb +18 -16
- data/lib/r18n-core/utils.rb +0 -12
- data/lib/r18n-core/version.rb +1 -1
- data/lib/r18n-core/yaml_loader.rb +67 -0
- data/lib/r18n-core.rb +25 -3
- data/locales/cs.rb +30 -16
- data/locales/de.rb +21 -0
- data/locales/en-us.rb +9 -4
- data/locales/en.rb +35 -20
- data/locales/eo.rb +20 -0
- data/locales/es.rb +20 -0
- data/locales/fr.rb +24 -9
- data/locales/it.rb +21 -9
- data/locales/kk.rb +26 -0
- data/locales/pl.rb +30 -18
- data/locales/pt-br.rb +24 -0
- data/locales/ru.rb +30 -12
- data/locales/zh.rb +19 -0
- data/spec/filters_spec.rb +24 -7
- data/spec/i18n_spec.rb +137 -50
- data/spec/locale_spec.rb +91 -53
- data/spec/locales/cs_spec.rb +9 -7
- data/spec/locales/pl_spec.rb +8 -9
- data/spec/locales/ru_spec.rb +9 -9
- data/spec/r18n_spec.rb +32 -13
- data/spec/spec_helper.rb +28 -4
- data/spec/translated_spec.rb +1 -1
- data/spec/translation_spec.rb +33 -67
- data/spec/translations/two/en.yml +0 -1
- data/spec/yaml_loader_spec.rb +33 -0
- metadata +11 -16
- data/locales/cs.yml +0 -26
- data/locales/de.yml +0 -26
- data/locales/en-us.yml +0 -10
- data/locales/en.yml +0 -26
- data/locales/eo.yml +0 -26
- data/locales/es.yml +0 -26
- data/locales/fr.yml +0 -26
- data/locales/it.yml +0 -26
- data/locales/kk.yml +0 -26
- data/locales/pl.yml +0 -26
- data/locales/pt-br.yml +0 -26
- data/locales/ru.yml +0 -26
- data/locales/zh.yml +0 -26
data/lib/r18n-core/i18n.rb
CHANGED
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
=end
|
20
20
|
|
21
21
|
require 'date'
|
22
|
+
require 'pathname'
|
22
23
|
|
23
24
|
module R18n
|
24
25
|
# General class to i18n support in your application. It load Translation and
|
@@ -28,8 +29,30 @@ module R18n
|
|
28
29
|
# translation’s name or <tt>[name]</tt> method. Translations will be also
|
29
30
|
# loaded for default locale, +sublocales+ from first in +locales+ and general
|
30
31
|
# languages for dialects (it will load +fr+ for +fr_CA+ too).
|
32
|
+
#
|
33
|
+
# Translations will loaded by loader object, which must have 2 methods:
|
34
|
+
# * <tt>available</tt> – return array of locales of available translations;
|
35
|
+
# * <tt>load(locale)</tt> – return Hash of translation.
|
36
|
+
# If you will use default loader (+R18n.default_loader+) you can pass to I18n
|
37
|
+
# only constructor argument for loader:
|
38
|
+
#
|
39
|
+
# R18n::I18n.new('en', R18n::Loader::YAML.new('dir/with/translations'))
|
40
|
+
#
|
41
|
+
# is a same as:
|
42
|
+
#
|
43
|
+
# R18n::I18n.new('en', 'dir/with/translations')
|
44
|
+
#
|
45
|
+
# In translation file you can use strings, numbers, floats (any YAML types)
|
46
|
+
# and pluralizable values (<tt>!!pl</tt>). You can use params in string
|
47
|
+
# values, which you can replace in program. Just write <tt>%1</tt>,
|
48
|
+
# <tt>%2</tt>, etc and set it values as method arguments, when you will be get
|
49
|
+
# value.
|
50
|
+
#
|
51
|
+
# You can use filters for some YAML type or for all strings. See R18n::Filters
|
52
|
+
# for details.
|
31
53
|
#
|
32
|
-
#
|
54
|
+
# R18n contain translations for common words (such as “OK”, “Cancel”, etc)
|
55
|
+
# for most supported locales. See <tt>base/</tt> dir.
|
33
56
|
#
|
34
57
|
# == Usage
|
35
58
|
# translations/ru.yml
|
@@ -57,6 +80,10 @@ module R18n
|
|
57
80
|
# i18n.l Time.now, :date #=> "21.09.2008"
|
58
81
|
# i18n.l Time.now, :time #=> "22:10"
|
59
82
|
# i18n.l Time.now, '%A' #=> "Воскресенье"
|
83
|
+
#
|
84
|
+
# i18n.yes #=> "Yes"
|
85
|
+
# i18n.ok #=> "OK"
|
86
|
+
# i18n.cancel #=> "Cancel"
|
60
87
|
class I18n
|
61
88
|
@@default = 'en'
|
62
89
|
|
@@ -87,27 +114,44 @@ module R18n
|
|
87
114
|
locales.map! { |i| i[0] }
|
88
115
|
end
|
89
116
|
|
117
|
+
# Return Array of locales with available translations.
|
118
|
+
def self.available_locales(places)
|
119
|
+
convert_places(places).map { |i| i.available }.flatten.uniq
|
120
|
+
end
|
121
|
+
|
122
|
+
# Load default loader for elements in +places+ with only constructor
|
123
|
+
# argument.
|
124
|
+
def self.convert_places(places)
|
125
|
+
Array(places).map! do |loader|
|
126
|
+
if loader.respond_to? :available and loader.respond_to? :load
|
127
|
+
loader
|
128
|
+
else
|
129
|
+
R18n.default_loader.new(loader)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
90
134
|
# User locales, ordered by priority
|
91
135
|
attr_reader :locales
|
92
136
|
|
93
|
-
#
|
94
|
-
attr_reader :
|
137
|
+
# Loaders with translations files
|
138
|
+
attr_reader :translation_places
|
95
139
|
|
96
140
|
# First locale with locale file
|
97
141
|
attr_reader :locale
|
98
142
|
|
99
|
-
# Create i18n for +locales+ with translations from +
|
143
|
+
# Create i18n for +locales+ with translations from +translation_places+ and
|
100
144
|
# locales data. Translations will be also loaded for default locale,
|
101
145
|
# +sublocales+ from first in +locales+ and general languages for dialects
|
102
146
|
# (it will load +fr+ for +fr_CA+ too).
|
103
147
|
#
|
104
148
|
# +Locales+ must be a locale code (RFC 3066) or array, ordered by priority.
|
105
|
-
# +
|
106
|
-
def initialize(locales,
|
107
|
-
locales =
|
149
|
+
# +Translation_places+ must be a string with path or array.
|
150
|
+
def initialize(locales, translation_places = nil)
|
151
|
+
locales = Array(locales)
|
108
152
|
|
109
153
|
if not locales.empty? and Locale.exists? locales.first
|
110
|
-
locales += Locale.load(locales.first)
|
154
|
+
locales += Locale.load(locales.first).sublocales
|
111
155
|
end
|
112
156
|
locales << @@default
|
113
157
|
locales.each_with_index do |locale, i|
|
@@ -115,18 +159,10 @@ module R18n
|
|
115
159
|
locales.insert(i + 1, locale.match(/([^_-]+)[_-]/)[1])
|
116
160
|
end
|
117
161
|
end
|
118
|
-
locales.uniq!
|
162
|
+
locales.map! { |i| i.to_s.downcase }.uniq!
|
163
|
+
@locales_codes = locales
|
119
164
|
@locales = locales.map { |i| Locale.load(i) }
|
120
165
|
|
121
|
-
if translation_dirs.nil?
|
122
|
-
@translation_dirs = []
|
123
|
-
@translation = Translation.load(@locales,
|
124
|
-
Translation.extension_translations)
|
125
|
-
else
|
126
|
-
@translation_dirs = translation_dirs
|
127
|
-
@translation = Translation.load(@locales, @translation_dirs)
|
128
|
-
end
|
129
|
-
|
130
166
|
@locale = @locales.first
|
131
167
|
unless @locale.supported?
|
132
168
|
@locales.each do |locale|
|
@@ -136,15 +172,58 @@ module R18n
|
|
136
172
|
end
|
137
173
|
end
|
138
174
|
end
|
175
|
+
|
176
|
+
if translation_places
|
177
|
+
@original_places = translation_places
|
178
|
+
else
|
179
|
+
@original_places = R18n.extension_places
|
180
|
+
end
|
181
|
+
|
182
|
+
@translation_places = self.class.convert_places(@original_places)
|
183
|
+
|
184
|
+
reload! unless @translation = R18n.cache[translation_cache_key]
|
139
185
|
end
|
140
186
|
|
141
|
-
|
142
|
-
#
|
143
|
-
def
|
144
|
-
|
145
|
-
all
|
146
|
-
|
187
|
+
|
188
|
+
# Return unique key for current locales in translation and places.
|
189
|
+
def translation_cache_key
|
190
|
+
available = @translation_places.inject([]) { |all, i|
|
191
|
+
all + i.available }.uniq.map { |i| i.code }
|
192
|
+
(@locales_codes & available).join(',') + '@' +
|
193
|
+
R18n.default_loader.hash.to_s +
|
194
|
+
@translation_places.hash.to_s + R18n.extension_places.hash.to_s
|
195
|
+
end
|
196
|
+
|
197
|
+
# Reload translations.
|
198
|
+
def reload!
|
199
|
+
@translation_places = self.class.convert_places(@original_places)
|
200
|
+
|
201
|
+
available_in_places = @translation_places.map { |i| [i, i.available] }
|
202
|
+
available_in_extensions = R18n.extension_places.map { |i| [i, i.available] }
|
203
|
+
|
204
|
+
@translation = Translation.new @locale
|
205
|
+
@locales.each do |locale|
|
206
|
+
loaded = false
|
207
|
+
available_in_places.each do |place, available|
|
208
|
+
if available.include? locale
|
209
|
+
@translation.merge! place.load(locale), locale
|
210
|
+
loaded = true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
if loaded
|
214
|
+
available_in_extensions.each do |extension, available|
|
215
|
+
if available.include? locale
|
216
|
+
@translation.merge! extension.load(locale), locale
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
147
220
|
end
|
221
|
+
R18n.cache[translation_cache_key] = @translation
|
222
|
+
end
|
223
|
+
|
224
|
+
# Return Array of locales with available translations.
|
225
|
+
def available_locales
|
226
|
+
@available ||= self.class.available_locales(@translation_places)
|
148
227
|
end
|
149
228
|
|
150
229
|
# Convert +object+ to String, according to the rules of the current locale.
|
@@ -161,30 +240,15 @@ module R18n
|
|
161
240
|
# i18n.l Time.now, :human #=> "now"
|
162
241
|
# i18n.l Time.now, :full #=> "Jule 1st, 2009 12:59"
|
163
242
|
def localize(object, format = nil, *params)
|
164
|
-
|
165
|
-
locale.format_integer(object)
|
166
|
-
elsif object.is_a? Float
|
167
|
-
locale.format_float(object)
|
168
|
-
elsif object.is_a? Time or object.is_a? DateTime or object.is_a? Date
|
169
|
-
if format.is_a? String
|
170
|
-
locale.strftime(object, format)
|
171
|
-
else
|
172
|
-
if :month == format
|
173
|
-
return locale.data['months']['standalone'][object.month - 1]
|
174
|
-
end
|
175
|
-
type = object.is_a?(Date) ? 'date' : 'time'
|
176
|
-
format = :standard unless format
|
177
|
-
|
178
|
-
unless [:human, :full, :standard].include? format
|
179
|
-
raise ArgumentError, "Unknown time formatter #{format}"
|
180
|
-
end
|
181
|
-
|
182
|
-
locale.send "format_#{type}_#{format}", self, object, *params
|
183
|
-
end
|
184
|
-
end
|
243
|
+
locale.localize(object, format, self, *params)
|
185
244
|
end
|
186
245
|
alias :l :localize
|
187
246
|
|
247
|
+
# Return translations.
|
248
|
+
def t
|
249
|
+
@translation
|
250
|
+
end
|
251
|
+
|
188
252
|
# Short and pretty way to get translation by method name. If translation
|
189
253
|
# has name like object methods (+new+, +to_s+, +methods+) use <tt>[]</tt>
|
190
254
|
# method to access.
|
@@ -192,7 +256,7 @@ module R18n
|
|
192
256
|
# Translation can contain variable part. Just set is as <tt>%1</tt>,
|
193
257
|
# <tt>%2</tt>, etc in translations file and set values as methods params.
|
194
258
|
def method_missing(name, *params)
|
195
|
-
@translation[name
|
259
|
+
@translation[name, *params]
|
196
260
|
end
|
197
261
|
|
198
262
|
# Return translation with special +name+.
|
data/lib/r18n-core/locale.rb
CHANGED
@@ -19,14 +19,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
=end
|
20
20
|
|
21
21
|
require 'pathname'
|
22
|
-
require '
|
22
|
+
require 'singleton'
|
23
23
|
|
24
24
|
module R18n
|
25
25
|
# Information about locale (language, country and other special variant
|
26
26
|
# preferences). Locale was named by RFC 3066. For example, locale for French
|
27
|
-
# speaking people in Canada will be +
|
27
|
+
# speaking people in Canada will be +fr-CA+.
|
28
28
|
#
|
29
|
-
# Locale
|
29
|
+
# Locale classes are placed in <tt>R18n::Locales</tt> module and storage
|
30
|
+
# install <tt>locales/</tt> dir.
|
30
31
|
#
|
31
32
|
# Each locale has +sublocales+ – often known languages for people from this
|
32
33
|
# locale. For example, many Belorussians know Russian and English. If there
|
@@ -44,110 +45,86 @@ module R18n
|
|
44
45
|
#
|
45
46
|
# == Available data
|
46
47
|
#
|
47
|
-
# * +code
|
48
|
-
# * +title
|
49
|
-
# * +
|
50
|
-
#
|
51
|
-
# * +
|
48
|
+
# * +code+ – locale RFC 3066 code;
|
49
|
+
# * +title+ – locale name on it language;
|
50
|
+
# * +ltr?+ – true on left-to-right writing direction, false for Arabic and
|
51
|
+
# Hebrew);
|
52
|
+
# * +sublocales+ – often known languages for people from this locale;
|
53
|
+
# * +week_start+ – does week start from +:monday+ or +:sunday+.
|
52
54
|
#
|
53
55
|
# You can see more available data about locale in samples in
|
54
56
|
# <tt>locales/</tt> dir.
|
55
|
-
#
|
56
|
-
# == Extend locale
|
57
|
-
# If language need some special logic (for example, another pluralization or
|
58
|
-
# time formatters) you can just change Locale class. Create
|
59
|
-
# R18n::Locales::_Code_ class in base/_code_.rb, extend R18n::Locale and
|
60
|
-
# rewrite methods (for example, +pluralization+ or +format_date_full+).
|
61
57
|
class Locale
|
62
58
|
LOCALES_DIR = Pathname(__FILE__).dirname.expand_path + '../../locales/'
|
59
|
+
|
60
|
+
@@loaded = {}
|
63
61
|
|
64
|
-
#
|
62
|
+
# Codes of all available locales.
|
65
63
|
def self.available
|
66
|
-
Dir.glob(File.join(LOCALES_DIR, '*.
|
67
|
-
File.basename(i, '.
|
64
|
+
Dir.glob(File.join(LOCALES_DIR, '*.rb')).map do |i|
|
65
|
+
File.basename(i, '.rb')
|
68
66
|
end
|
69
67
|
end
|
70
68
|
|
71
|
-
# Is +locale+ has info file
|
69
|
+
# Is +locale+ has info file.
|
72
70
|
def self.exists?(locale)
|
73
|
-
File.exists?(File.join(LOCALES_DIR, locale + '.
|
71
|
+
File.exists?(File.join(LOCALES_DIR, locale.to_s + '.rb'))
|
74
72
|
end
|
75
73
|
|
76
|
-
# Load locale by RFC 3066 +code
|
74
|
+
# Load locale by RFC 3066 +code+.
|
77
75
|
def self.load(code)
|
78
|
-
|
79
|
-
code.
|
80
|
-
code.delete! '\\'
|
81
|
-
code.delete! ';'
|
82
|
-
original = code
|
83
|
-
code = code.downcase
|
84
|
-
|
85
|
-
return UnsupportedLocale.new(original) unless exists? code
|
86
|
-
|
87
|
-
data = {}
|
88
|
-
klass = R18n::Locale
|
89
|
-
default_loaded = false
|
76
|
+
original = code.to_s.gsub(/[^-a-zA-Z]/, '')
|
77
|
+
code = original.downcase
|
90
78
|
|
91
|
-
|
92
|
-
|
93
|
-
default_loaded = true if I18n.default == code
|
94
|
-
|
95
|
-
if R18n::Locale == klass and File.exists? LOCALES_DIR + "#{code}.rb"
|
79
|
+
@@loaded[code] ||= begin
|
80
|
+
if exists? code
|
96
81
|
require LOCALES_DIR + "#{code}.rb"
|
97
82
|
name = code.gsub(/[\w\d]+/) { |i| i.capitalize }.gsub('-', '')
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
loaded = YAML.load_file(file)
|
102
|
-
code = loaded['include']
|
103
|
-
data = Utils.deep_merge! loaded, data
|
104
|
-
end
|
105
|
-
|
106
|
-
unless default_loaded
|
107
|
-
code = I18n.default
|
108
|
-
while code and exists? code
|
109
|
-
loaded = YAML.load_file(LOCALES_DIR + "#{code}.yml")
|
110
|
-
code = loaded['include']
|
111
|
-
data = Utils.deep_merge! loaded, data
|
83
|
+
eval('R18n::Locales::' + name).new
|
84
|
+
else
|
85
|
+
UnsupportedLocale.new(original)
|
112
86
|
end
|
113
87
|
end
|
114
|
-
|
115
|
-
klass.new(data)
|
116
88
|
end
|
117
89
|
|
118
|
-
|
119
|
-
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
|
125
|
-
|
90
|
+
# Set locale +properties+. Locale class will have methods for each propetry
|
91
|
+
# name, which return propetry value:
|
92
|
+
#
|
93
|
+
# class R18n::Locales::En < R18n::Locale
|
94
|
+
# set :title => 'English',
|
95
|
+
# :code => 'en'
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# locale = R18n::Locales::En.new
|
99
|
+
# locale.title #=> "English"
|
100
|
+
# locale.code #=> "en"
|
101
|
+
def self.set(properties)
|
102
|
+
properties.each_pair do |key, value|
|
103
|
+
define_method(key) { value }
|
104
|
+
end
|
126
105
|
end
|
127
106
|
|
128
107
|
# Locale RFC 3066 code.
|
129
108
|
def code
|
130
|
-
|
109
|
+
self.class.name.split('::').last.downcase
|
131
110
|
end
|
132
111
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
112
|
+
set :sublocales => %w{en},
|
113
|
+
:week_start => :monday,
|
114
|
+
:time_am => 'AM',
|
115
|
+
:time_pm => 'PM',
|
116
|
+
:time_format => ' %H:%M',
|
117
|
+
:full_format => '%e %B',
|
118
|
+
:year_format => '_ %Y'
|
119
|
+
|
120
|
+
def month_standalone; month_names; end
|
137
121
|
|
138
122
|
# Is locale has left-to-right write direction.
|
139
|
-
def ltr
|
140
|
-
@data['direction'] == 'ltr'
|
141
|
-
end
|
142
|
-
|
143
|
-
# Get information about locale
|
144
|
-
def [](name)
|
145
|
-
@data[name]
|
146
|
-
end
|
123
|
+
def ltr?; true; end
|
147
124
|
|
148
|
-
# Is another locale has same code
|
125
|
+
# Is another locale has same code.
|
149
126
|
def ==(locale)
|
150
|
-
|
127
|
+
self.class == locale.class
|
151
128
|
end
|
152
129
|
|
153
130
|
# Is locale has information file. In this class always return true.
|
@@ -155,17 +132,48 @@ module R18n
|
|
155
132
|
true
|
156
133
|
end
|
157
134
|
|
158
|
-
# Human readable locale code and title
|
135
|
+
# Human readable locale code and title.
|
159
136
|
def inspect
|
160
137
|
"Locale #{code} (#{title})"
|
161
138
|
end
|
162
139
|
|
140
|
+
# Convert +object+ to String. It support Fixnum, Bignum, Float, Time, Date
|
141
|
+
# and DateTime.
|
142
|
+
#
|
143
|
+
# For time classes you can set +format+ in standard +strftime+ form,
|
144
|
+
# <tt>:full</tt> (“01 Jule, 2009”), <tt>:human</tt> (“yesterday”),
|
145
|
+
# <tt>:standard</tt> (“07/01/09”) or <tt>:month</tt> for standalone month
|
146
|
+
# name. Default format is <tt>:standard</tt>.
|
147
|
+
def localize(obj, format = nil, *params)
|
148
|
+
case obj
|
149
|
+
when Integer
|
150
|
+
format_integer(obj)
|
151
|
+
when Float
|
152
|
+
format_float(obj)
|
153
|
+
when Time, DateTime, Date
|
154
|
+
return strftime(obj, format) if format.is_a? String
|
155
|
+
return month_standalone[obj.month - 1] if :month == format
|
156
|
+
return obj.to_s if :human == format and not params.first.is_a? I18n
|
157
|
+
|
158
|
+
type = obj.is_a?(Date) ? 'date' : 'time'
|
159
|
+
format = :standard unless format
|
160
|
+
|
161
|
+
unless [:human, :full, :standard].include? format
|
162
|
+
raise ArgumentError, "Unknown time formatter #{format}"
|
163
|
+
end
|
164
|
+
|
165
|
+
send "format_#{type}_#{format}", obj, *params
|
166
|
+
else
|
167
|
+
obj.to_s
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
163
171
|
# Returns the integer in String form, according to the rules of the locale.
|
164
172
|
# It will also put real typographic minus.
|
165
173
|
def format_integer(integer)
|
166
174
|
str = integer.to_s
|
167
175
|
str[0] = '−' if 0 > integer # Real typographic minus
|
168
|
-
group =
|
176
|
+
group = number_group
|
169
177
|
|
170
178
|
str.gsub(/(\d)(?=(\d\d\d)+(?!\d))/) do |match|
|
171
179
|
match + group
|
@@ -175,7 +183,7 @@ module R18n
|
|
175
183
|
# Returns the float in String form, according to the rules of the locale.
|
176
184
|
# It will also put real typographic minus.
|
177
185
|
def format_float(float)
|
178
|
-
decimal =
|
186
|
+
decimal = number_decimal
|
179
187
|
self.format_integer(float.to_i) + decimal + float.to_s.split('.').last
|
180
188
|
end
|
181
189
|
|
@@ -187,19 +195,15 @@ module R18n
|
|
187
195
|
format.scan(/%[EO]?.|./o) do |c|
|
188
196
|
case c.sub(/^%[EO]?(.)$/o, '%\\1')
|
189
197
|
when '%A'
|
190
|
-
translated <<
|
198
|
+
translated << wday_names[time.wday]
|
191
199
|
when '%a'
|
192
|
-
translated <<
|
200
|
+
translated << wday_abbrs[time.wday]
|
193
201
|
when '%B'
|
194
|
-
translated <<
|
202
|
+
translated << month_names[time.month - 1]
|
195
203
|
when '%b'
|
196
|
-
translated <<
|
204
|
+
translated << month_abbrs[time.month - 1]
|
197
205
|
when '%p'
|
198
|
-
translated <<
|
199
|
-
@data['time']['am']
|
200
|
-
else
|
201
|
-
@data['time']['pm']
|
202
|
-
end
|
206
|
+
translated << (time.hour < 12 ? time_am : time_pm)
|
203
207
|
else
|
204
208
|
translated << c
|
205
209
|
end
|
@@ -209,17 +213,17 @@ module R18n
|
|
209
213
|
|
210
214
|
# Format +time+ without date. For example, “12:59”.
|
211
215
|
def format_time(time)
|
212
|
-
strftime(time,
|
216
|
+
strftime(time, time_format)
|
213
217
|
end
|
214
218
|
|
215
219
|
# Format +time+ in human usable form. For example “5 minutes ago” or
|
216
220
|
# “yesterday”. In +now+ you can set base time, which be used to get relative
|
217
221
|
# time. For special cases you can replace it in locale’s class.
|
218
|
-
def format_time_human(
|
222
|
+
def format_time_human(time, i18n, now = Time.now, *params)
|
219
223
|
minutes = (time - now) / 60.0
|
220
224
|
if time.mday != now.mday and minutes.abs > 720 # 12 hours
|
221
|
-
format_date_human(
|
222
|
-
|
225
|
+
format_date_human(R18n::Utils.to_date(time), i18n,
|
226
|
+
R18n::Utils.to_date(now)) + format_time(time)
|
223
227
|
else
|
224
228
|
case minutes
|
225
229
|
when -60..-1
|
@@ -240,20 +244,20 @@ module R18n
|
|
240
244
|
end
|
241
245
|
|
242
246
|
# Format +time+ in compact form. For example, “12/31/09 12:59”.
|
243
|
-
def format_time_standard(
|
244
|
-
format_date_standard(
|
247
|
+
def format_time_standard(time, *params)
|
248
|
+
format_date_standard(time) + format_time(time)
|
245
249
|
end
|
246
250
|
|
247
251
|
# Format +time+ in most official form. For example, “December 31st, 2009
|
248
252
|
# 12:59”. For special cases you can replace it in locale’s class.
|
249
|
-
def format_time_full(
|
250
|
-
format_date_full(
|
253
|
+
def format_time_full(time, *params)
|
254
|
+
format_date_full(time) + format_time(time)
|
251
255
|
end
|
252
256
|
|
253
257
|
# Format +date+ in human usable form. For example “5 days ago” or
|
254
258
|
# “yesterday”. In +now+ you can set base time, which be used to get relative
|
255
259
|
# time. For special cases you can replace it in locale’s class.
|
256
|
-
def format_date_human(
|
260
|
+
def format_date_human(date, i18n, now = Date.today, *params)
|
257
261
|
days = (date - now).to_i
|
258
262
|
case days
|
259
263
|
when -6..-2
|
@@ -267,21 +271,21 @@ module R18n
|
|
267
271
|
when 2..6
|
268
272
|
i18n.human_time.after_days(days)
|
269
273
|
else
|
270
|
-
format_date_full(
|
274
|
+
format_date_full(date, date.year != now.year)
|
271
275
|
end
|
272
276
|
end
|
273
277
|
|
274
278
|
# Format +date+ in compact form. For example, “12/31/09”.
|
275
|
-
def format_date_standard(
|
276
|
-
strftime(date,
|
279
|
+
def format_date_standard(date, *params)
|
280
|
+
strftime(date, date_format)
|
277
281
|
end
|
278
282
|
|
279
283
|
# Format +date+ in most official form. For example, “December 31st, 2009”.
|
280
284
|
# For special cases you can replace it in locale’s class. If +year+ is false
|
281
285
|
# date will be without year.
|
282
|
-
def format_date_full(
|
283
|
-
format =
|
284
|
-
format =
|
286
|
+
def format_date_full(date, year = true, *params)
|
287
|
+
format = full_format
|
288
|
+
format = year_format.sub('_', format) if year
|
285
289
|
strftime(date, format)
|
286
290
|
end
|
287
291
|
|
@@ -298,4 +302,6 @@ module R18n
|
|
298
302
|
end
|
299
303
|
end
|
300
304
|
end
|
305
|
+
|
306
|
+
module Locales; end
|
301
307
|
end
|
data/lib/r18n-core/translated.rb
CHANGED
@@ -123,8 +123,6 @@ module R18n
|
|
123
123
|
|
124
124
|
class_eval <<-EOS, __FILE__, __LINE__
|
125
125
|
def #{name}(*params)
|
126
|
-
path = "\#{self.class.name}##{name}"
|
127
|
-
|
128
126
|
unlocalized = self.class.unlocalized_getters(#{name.inspect})
|
129
127
|
R18n.get.locales.each do |locale|
|
130
128
|
code = locale.code
|
@@ -132,11 +130,18 @@ module R18n
|
|
132
130
|
result = method(unlocalized[code]).#{call}
|
133
131
|
next unless result
|
134
132
|
|
133
|
+
path = "\#{self.class.name}##{name}"
|
135
134
|
type = self.class.translation_types[#{name.inspect}]
|
136
|
-
|
135
|
+
if type
|
136
|
+
return R18n::Filters.process(type, result, locale, path, params)
|
137
|
+
else
|
138
|
+
result = TranslatedString.new(result, locale, path)
|
139
|
+
return R18n::Filters.process_string(result, path, params)
|
140
|
+
end
|
137
141
|
end
|
138
142
|
|
139
|
-
R18n::Untranslated.new(
|
143
|
+
R18n::Untranslated.new("\#{self.class.name}\#", '#{name}',
|
144
|
+
R18n.get.locale)
|
140
145
|
end
|
141
146
|
EOS
|
142
147
|
|