r18n-core 0.3.2 → 0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|