r18n-core 0.4.10 → 0.4.11
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 +5 -0
- data/Gemfile.lock +1 -1
- data/README.rdoc +25 -25
- data/Rakefile +0 -1
- data/lib/r18n-core.rb +5 -5
- data/lib/r18n-core/filters.rb +45 -45
- data/lib/r18n-core/helpers.rb +4 -4
- data/lib/r18n-core/i18n.rb +30 -30
- data/lib/r18n-core/locale.rb +26 -26
- data/lib/r18n-core/translated.rb +23 -23
- data/lib/r18n-core/translated_string.rb +4 -4
- data/lib/r18n-core/translation.rb +10 -10
- data/lib/r18n-core/unsupported_locale.rb +6 -6
- data/lib/r18n-core/untranslated.rb +13 -13
- data/lib/r18n-core/utils.rb +4 -4
- data/lib/r18n-core/version.rb +1 -1
- data/lib/r18n-core/yaml_loader.rb +13 -11
- data/locales/bg.rb +3 -3
- data/locales/ca.rb +6 -5
- data/locales/cs.rb +5 -5
- data/locales/da.rb +4 -4
- data/locales/de.rb +4 -4
- data/locales/en-us.rb +1 -1
- data/locales/en.rb +6 -6
- data/locales/eo.rb +4 -4
- data/locales/es.rb +4 -4
- data/locales/fi.rb +5 -5
- data/locales/fr.rb +6 -6
- data/locales/hu.rb +1 -1
- data/locales/it.rb +5 -5
- data/locales/ja.rb +5 -4
- data/locales/kk.rb +4 -4
- data/locales/lv.rb +5 -5
- data/locales/nl.rb +5 -5
- data/locales/pl.rb +5 -5
- data/locales/pt.rb +4 -4
- data/locales/ru.rb +5 -5
- data/locales/sk.rb +5 -5
- data/locales/sv-se.rb +4 -4
- data/locales/th.rb +7 -4
- data/locales/zh.rb +6 -5
- data/r18n-core.gemspec +0 -1
- data/spec/filters_spec.rb +48 -48
- data/spec/i18n_spec.rb +32 -32
- data/spec/locale_spec.rb +20 -20
- data/spec/locales/cs_spec.rb +2 -2
- data/spec/locales/hu_spec.rb +1 -1
- data/spec/locales/it_spec.rb +1 -1
- data/spec/locales/pl_spec.rb +2 -2
- data/spec/locales/ru_spec.rb +3 -3
- data/spec/locales/sk_spec.rb +2 -2
- data/spec/r18n_spec.rb +21 -21
- data/spec/spec_helper.rb +3 -3
- data/spec/translated_spec.rb +24 -24
- data/spec/translation_spec.rb +10 -10
- data/spec/yaml_loader_spec.rb +10 -10
- metadata +24 -26
data/ChangeLog
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
== 0.4.11 (Nancy)
|
2
|
+
* Support for Sinatra 1.3.
|
3
|
+
* Fix JRuby support by Paul Walker.
|
4
|
+
* Add R18n helpers to Rails mailer by Alexey Medvedev.
|
5
|
+
|
1
6
|
== 0.4.10 (Kvantum)
|
2
7
|
* Add R18n.set(locales, places), R18n.t and R18n.l shortcuts.
|
3
8
|
* Convert float to number on pluralization.
|
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -24,7 +24,7 @@ To access translation you can call methods with the same names:
|
|
24
24
|
t.user.edit #=> "Edit user"
|
25
25
|
t.user.name('John') #=> "User name is John"
|
26
26
|
t.user.count(5) #=> "There are 5 users"
|
27
|
-
|
27
|
+
|
28
28
|
t.not.exists | 'default' #=> "default"
|
29
29
|
t.not.exists.translated? #=> false
|
30
30
|
|
@@ -85,7 +85,7 @@ need to create loader object with 2 methods: +available+ and +load+:
|
|
85
85
|
Translation.find(locale).to_hash
|
86
86
|
end
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
R18n.set(user_locales, DBLoader.new)
|
90
90
|
|
91
91
|
You can also set a list of different translation locations or set extension
|
@@ -98,16 +98,16 @@ You can translate any class, including ORM models (ActiveRecord, DataMapper,
|
|
98
98
|
MongoMapper, Mongoid or others):
|
99
99
|
|
100
100
|
require 'r18n-core/translated'
|
101
|
-
|
101
|
+
|
102
102
|
class Product < ActiveRecord::Base
|
103
103
|
include R18n::Translated
|
104
104
|
# Model has two normal properties: title_en and title_ru
|
105
105
|
translations :title
|
106
106
|
end
|
107
|
-
|
107
|
+
|
108
108
|
# For English users
|
109
109
|
product.title #=> "Anthrax"
|
110
|
-
|
110
|
+
|
111
111
|
# For Russian users
|
112
112
|
product.title #=> "Сибирская язва"
|
113
113
|
|
@@ -128,10 +128,10 @@ cultures with two official languages (e.g., exUSSR) it takes the second language
|
|
128
128
|
(e.g., if a translation isn’t available in Kazakh R18n will look for Russian):
|
129
129
|
|
130
130
|
i18n = R18n::I18n.new(['kk', 'de'], 'dir/with/translations')
|
131
|
-
|
131
|
+
|
132
132
|
i18n.locales #=> [Locale kk (Қазақша), Locale de (Deutsch),
|
133
133
|
# Locale ru (Русский), Locale en (English)]
|
134
|
-
|
134
|
+
|
135
135
|
i18n.kazakh #=> "Қазақша", main user language
|
136
136
|
i18n.deutsch #=> "Deutsch", not in Kazakh, use next user locale
|
137
137
|
i18n.russian #=> "Русский", not in kk and de, use Kazakh sublocale
|
@@ -153,11 +153,11 @@ create an I18n object and by using <tt>R18n.set</tt> or, for the current thread,
|
|
153
153
|
by using <tt>R18n.thread_set</tt>:
|
154
154
|
|
155
155
|
R18n.set('en', 'path/to/translations')
|
156
|
-
|
156
|
+
|
157
157
|
You can add helpers to access the current R18n object:
|
158
158
|
|
159
159
|
include R18n::Helpers
|
160
|
-
|
160
|
+
|
161
161
|
t.yes #=> "Yes"
|
162
162
|
l Time.now, :human #=> "now"
|
163
163
|
r18n.locale.code #=> "en"
|
@@ -206,7 +206,7 @@ instance or code string if locale is’t supported in R18n):
|
|
206
206
|
i18n.not.in.english.locale #=> Locale ru (Русский)
|
207
207
|
|
208
208
|
You can include parameters in the translated string by specifying arguments:
|
209
|
-
|
209
|
+
|
210
210
|
name: "My name is %1"
|
211
211
|
|
212
212
|
t.name('John') #=> "My name is John"
|
@@ -252,7 +252,7 @@ loaded.
|
|
252
252
|
friendship: !!gender
|
253
253
|
f: She adds a friend
|
254
254
|
m: He adds a friend
|
255
|
-
|
255
|
+
|
256
256
|
R18n::Filters.add('gender', :user_gender) do |content, config, user|
|
257
257
|
if user.female?
|
258
258
|
content['f']
|
@@ -260,9 +260,9 @@ loaded.
|
|
260
260
|
content['m']
|
261
261
|
end
|
262
262
|
end
|
263
|
-
|
263
|
+
|
264
264
|
t.friendship(anne) #=> "She adds a friend"
|
265
|
-
|
265
|
+
|
266
266
|
To create a filter you pass the following to <tt>R18n::Filters.add</tt>:
|
267
267
|
|
268
268
|
* Filter target. YAML type (<tt>!!type</tt>), <tt>String</tt> for all
|
@@ -365,26 +365,26 @@ You can add i18n support to any classes, including ORM models (ActiveRecord,
|
|
365
365
|
DataMapper, MongoMapper, Mongoid or others):
|
366
366
|
|
367
367
|
require 'r18n-core/translated'
|
368
|
-
|
368
|
+
|
369
369
|
class Product
|
370
370
|
include DataMapper::Resource
|
371
371
|
property :title_ru, String
|
372
372
|
property :title_en, String
|
373
|
-
|
373
|
+
|
374
374
|
include R18n::Translated
|
375
375
|
translations :title
|
376
376
|
end
|
377
|
-
|
377
|
+
|
378
378
|
# For example, user only knows Russian
|
379
|
-
|
379
|
+
|
380
380
|
# Set English (default) title
|
381
381
|
product.title_en = "Anthrax"
|
382
382
|
product.title #=> "Anthrax"
|
383
|
-
|
383
|
+
|
384
384
|
# Set value for user locale (Russian)
|
385
385
|
product.title = "Сибирская язва"
|
386
386
|
product.title #=> "Сибирская язва"
|
387
|
-
|
387
|
+
|
388
388
|
product.title_en #=> "Anthrax"
|
389
389
|
product.title_ru #=> "Сибирская язва"
|
390
390
|
|
@@ -403,16 +403,16 @@ To get information about a locale create an R18n::Locale instance:
|
|
403
403
|
You can then get the following from the locale:
|
404
404
|
|
405
405
|
* Locale title and RFC 3066 code:
|
406
|
-
|
406
|
+
|
407
407
|
locale.title #=> "English"
|
408
408
|
locale.code #=> "en"
|
409
|
-
|
409
|
+
|
410
410
|
* Language direction (left to right, or right to left for Arabic and Hebrew):
|
411
|
-
|
411
|
+
|
412
412
|
locale.ltr? #=> true
|
413
|
-
|
413
|
+
|
414
414
|
* Week start day (+:monday+ or +:sunday+):
|
415
|
-
|
415
|
+
|
416
416
|
locale.week_start #=> :sunday
|
417
417
|
|
418
418
|
=== Loaders
|
@@ -438,7 +438,7 @@ If you want to load a translation with some type for filter, use
|
|
438
438
|
|
439
439
|
# Loader will return something like:
|
440
440
|
{ 'users' => R18n::Typed.new('pl', { 1 => '1 user', 'n' => '%1 users' }) }
|
441
|
-
|
441
|
+
|
442
442
|
# To use pluralization filter (+pl+ type):
|
443
443
|
t.users(5) #=> "5 users"
|
444
444
|
|
data/Rakefile
CHANGED
data/lib/r18n-core.rb
CHANGED
@@ -37,7 +37,7 @@ require dir + 'helpers'
|
|
37
37
|
|
38
38
|
module R18n
|
39
39
|
class << self
|
40
|
-
|
40
|
+
|
41
41
|
# Set I18n object globally.
|
42
42
|
def set(i18n = nil, dir = nil, &block)
|
43
43
|
if block_given?
|
@@ -76,12 +76,12 @@ module R18n
|
|
76
76
|
def thread
|
77
77
|
Thread.current
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
# Translate message. Alias for <tt>R18n.get.t</tt>.
|
81
81
|
def t(*params)
|
82
82
|
get.t(*params)
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
# Localize object. Alias for <tt>R18n.get.l</tt>.
|
86
86
|
def l(*params)
|
87
87
|
get.l(*params)
|
@@ -94,11 +94,11 @@ module R18n
|
|
94
94
|
# Loaders with extension translations. If application translations with
|
95
95
|
# same locale isn’t exists, extension file willn’t be used.
|
96
96
|
attr_accessor :extension_places
|
97
|
-
|
97
|
+
|
98
98
|
# Hash of hash-like (see Moneta) object to store loaded translations.
|
99
99
|
attr_accessor :cache
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
self.default_loader = R18n::Loader::YAML
|
103
103
|
self.extension_places = [
|
104
104
|
Loader::YAML.new(Pathname(__FILE__).dirname.expand_path + '../base')]
|
data/lib/r18n-core/filters.rb
CHANGED
@@ -19,55 +19,55 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
=end
|
20
20
|
|
21
21
|
require 'ostruct'
|
22
|
-
|
22
|
+
|
23
23
|
module R18n
|
24
24
|
# Filter is a way, to process translations: escape HTML entries, convert from
|
25
25
|
# Markdown syntax, etc.
|
26
|
-
#
|
26
|
+
#
|
27
27
|
# In translation file filtered content must be marked by YAML type:
|
28
|
-
#
|
28
|
+
#
|
29
29
|
# filtered: !!custom_type
|
30
30
|
# This content will be processed by filter
|
31
|
-
#
|
31
|
+
#
|
32
32
|
# Filter function will be receive filtered content as first argument, struct
|
33
33
|
# with filter config as second and filter parameters as next arguments. You
|
34
34
|
# can set passive filter, which will process translation only on loading.
|
35
|
-
#
|
35
|
+
#
|
36
36
|
# R18n::Filters.add('custom_type', :no_space) do |content, config, replace|
|
37
37
|
# content.gsub(' ', replace)
|
38
38
|
# end
|
39
39
|
# R18n::Filters.add('custom_type', :passive => true) do |content, config|
|
40
40
|
# content + '!'
|
41
41
|
# end
|
42
|
-
#
|
42
|
+
#
|
43
43
|
# i18n.filtered('_') #=> "This_content_will_be_processed_by_filter!"
|
44
44
|
#
|
45
45
|
# Use String class as type to add global filter for all translated strings:
|
46
|
-
#
|
46
|
+
#
|
47
47
|
# R18n::Filters.add(String, :escape_html) do |content, config, params|
|
48
48
|
# escape_html(content)
|
49
49
|
# end
|
50
50
|
#
|
51
51
|
# Filter config contain two parameters: translation locale and path. But it is
|
52
52
|
# Hash and you can add you own parameter to cross-filter communications:
|
53
|
-
#
|
53
|
+
#
|
54
54
|
# R18n::Filters.add(String, :hide_truth) do |content, config|
|
55
55
|
# return content if config[:censorship_check]
|
56
|
-
#
|
56
|
+
#
|
57
57
|
# if content.scan(CENSORSHIP_WORDS[config[:locale]]).empty?
|
58
58
|
# content
|
59
59
|
# else
|
60
60
|
# "Error in #{config[:path]}"
|
61
61
|
# end
|
62
62
|
# end
|
63
|
-
#
|
63
|
+
#
|
64
64
|
# R18n::Filters.add('passed', :show_lie) do |content, config|
|
65
65
|
# config[:censorship_check] = true
|
66
66
|
# content
|
67
67
|
# end
|
68
|
-
#
|
68
|
+
#
|
69
69
|
# You can disable, enabled and delete filters:
|
70
|
-
#
|
70
|
+
#
|
71
71
|
# R18n::Filters.off(:no_space))
|
72
72
|
# i18n.filtered('_') #=> "This content will be processed by filter!"
|
73
73
|
# R18n::Filters.on(:no_space)
|
@@ -77,27 +77,27 @@ module R18n
|
|
77
77
|
class << self
|
78
78
|
# Hash of filter names to Filters.
|
79
79
|
attr_accessor :defined
|
80
|
-
|
80
|
+
|
81
81
|
# Hash of types to all Filters.
|
82
82
|
attr_accessor :by_type
|
83
|
-
|
83
|
+
|
84
84
|
# Hash of types to enabled active filters.
|
85
85
|
attr_accessor :active_enabled
|
86
|
-
|
86
|
+
|
87
87
|
# Hash of types to enabled passive filters.
|
88
88
|
attr_accessor :passive_enabled
|
89
|
-
|
89
|
+
|
90
90
|
# Hash of types to enabled passive and active filters.
|
91
91
|
attr_accessor :enabled
|
92
|
-
|
92
|
+
|
93
93
|
# Process +value+ by filters in +enabled+.
|
94
94
|
def process(enabled, type, value, locale, path, params)
|
95
95
|
config = { :locale => locale, :path => path }
|
96
|
-
|
96
|
+
|
97
97
|
enabled[type].each do |filter|
|
98
98
|
value = filter.call(value, config, *params)
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
if value.is_a? String
|
102
102
|
value = TranslatedString.new(value, locale, path)
|
103
103
|
process_string(enabled, value, config, params)
|
@@ -105,7 +105,7 @@ module R18n
|
|
105
105
|
value
|
106
106
|
end
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
# Process +value+ by global filters in +enabled+.
|
110
110
|
def process_string(enabled, value, config, params)
|
111
111
|
if config.is_a? String
|
@@ -116,13 +116,13 @@ module R18n
|
|
116
116
|
end
|
117
117
|
value
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
# Rebuild +active_enabled+ and +passive_enabled+ for +type+.
|
121
121
|
def rebuild_enabled!(type)
|
122
122
|
@passive_enabled[type] = []
|
123
123
|
@active_enabled[type] = []
|
124
124
|
@enabled[type] = []
|
125
|
-
|
125
|
+
|
126
126
|
@by_type[type].each do |filter|
|
127
127
|
if filter.enabled?
|
128
128
|
@enabled[type] << filter
|
@@ -134,7 +134,7 @@ module R18n
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
137
|
-
|
137
|
+
|
138
138
|
# Add new filter for +type+ with +name+ and return filter object. You
|
139
139
|
# can use String class as +type+ to add global filter for all translated
|
140
140
|
# string.
|
@@ -150,7 +150,7 @@ module R18n
|
|
150
150
|
def add(types, name = nil, options = {}, &block)
|
151
151
|
options, name = name, nil if name.is_a? Hash
|
152
152
|
types = Array(types)
|
153
|
-
|
153
|
+
|
154
154
|
unless name
|
155
155
|
@last_auto_name ||= 0
|
156
156
|
begin
|
@@ -160,10 +160,10 @@ module R18n
|
|
160
160
|
else
|
161
161
|
delete(name)
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
filter = Filter.new(name, types, block, true, options[:passive])
|
165
165
|
@defined[name] = filter
|
166
|
-
|
166
|
+
|
167
167
|
types.each do |type|
|
168
168
|
@by_type[type] = [] unless @by_type.has_key? type
|
169
169
|
if options.has_key? :position
|
@@ -173,58 +173,58 @@ module R18n
|
|
173
173
|
end
|
174
174
|
rebuild_enabled! type
|
175
175
|
end
|
176
|
-
|
176
|
+
|
177
177
|
filter
|
178
178
|
end
|
179
|
-
|
179
|
+
|
180
180
|
# Delete +filter+ by name or Filter object.
|
181
181
|
def delete(filter)
|
182
182
|
filter = @defined[filter] unless filter.is_a? Filter
|
183
183
|
return unless filter
|
184
|
-
|
184
|
+
|
185
185
|
@defined.delete(filter.name)
|
186
186
|
filter.types.each do |type|
|
187
187
|
@by_type[type].delete(filter)
|
188
188
|
rebuild_enabled! type
|
189
189
|
end
|
190
190
|
end
|
191
|
-
|
191
|
+
|
192
192
|
# Disable +filter+ by name or Filter object.
|
193
193
|
def off(filter)
|
194
194
|
filter = @defined[filter] unless filter.is_a? Filter
|
195
195
|
return unless filter
|
196
|
-
|
196
|
+
|
197
197
|
filter.enabled = false
|
198
198
|
filter.types.each { |type| rebuild_enabled! type }
|
199
199
|
end
|
200
|
-
|
200
|
+
|
201
201
|
# Turn on disabled +filter+ by name or Filter object.
|
202
202
|
def on(filter)
|
203
203
|
filter = @defined[filter] unless filter.is_a? Filter
|
204
204
|
return unless filter
|
205
|
-
|
205
|
+
|
206
206
|
filter.enabled = true
|
207
207
|
filter.types.each { |type| rebuild_enabled! type }
|
208
208
|
end
|
209
209
|
end
|
210
|
-
|
210
|
+
|
211
211
|
Filters.defined = {}
|
212
212
|
Filters.by_type = Hash.new([])
|
213
213
|
Filters.active_enabled = Hash.new([])
|
214
214
|
Filters.passive_enabled = Hash.new([])
|
215
215
|
Filters.enabled = Hash.new([])
|
216
|
-
|
216
|
+
|
217
217
|
Filter = Struct.new(:name, :types, :block, :enabled, :passive) do
|
218
218
|
def call(*params); block.call(*params); end
|
219
219
|
def enabled?; enabled; end
|
220
220
|
def passive?; passive; end
|
221
221
|
end
|
222
222
|
end
|
223
|
-
|
223
|
+
|
224
224
|
Filters.add('proc', :procedure) do |content, config, *params|
|
225
225
|
eval("proc { #{content} }").call(*params)
|
226
226
|
end
|
227
|
-
|
227
|
+
|
228
228
|
Filters.add('pl', :pluralization) do |content, config, param|
|
229
229
|
param = param.to_i if param.is_a? Float
|
230
230
|
if param.is_a? Numeric
|
@@ -235,7 +235,7 @@ module R18n
|
|
235
235
|
content
|
236
236
|
end
|
237
237
|
end
|
238
|
-
|
238
|
+
|
239
239
|
Filters.add(String, :variables) do |content, config, *params|
|
240
240
|
content = content.clone
|
241
241
|
params.each_with_index do |param, i|
|
@@ -243,27 +243,27 @@ module R18n
|
|
243
243
|
end
|
244
244
|
content
|
245
245
|
end
|
246
|
-
|
246
|
+
|
247
247
|
Filters.add(Untranslated, :untranslated) do |v, c, translated, untranslated|
|
248
248
|
"#{translated}[#{untranslated}]"
|
249
249
|
end
|
250
|
-
|
250
|
+
|
251
251
|
Filters.add(Untranslated, :untranslated_html) do |v, c, transl, untransl|
|
252
252
|
Utils.escape_html(transl) <<
|
253
253
|
'<span style="color: red">' << Utils.escape_html(untransl) << '</span>'
|
254
254
|
end
|
255
255
|
Filters.off(:untranslated_html)
|
256
|
-
|
256
|
+
|
257
257
|
Filters.add('escape', :escape_html, :passive => true) do |content, config|
|
258
258
|
config[:dont_escape_html] = true
|
259
259
|
Utils.escape_html(content)
|
260
260
|
end
|
261
|
-
|
261
|
+
|
262
262
|
Filters.add('html', :dont_escape_html, :passive => true) do |content, config|
|
263
263
|
config[:dont_escape_html] = true
|
264
264
|
content
|
265
265
|
end
|
266
|
-
|
266
|
+
|
267
267
|
Filters.add([String, 'markdown', 'textile'],
|
268
268
|
:global_escape_html, :passive => true) do |html, config|
|
269
269
|
if config[:dont_escape_html]
|
@@ -274,12 +274,12 @@ module R18n
|
|
274
274
|
end
|
275
275
|
end
|
276
276
|
Filters.off(:global_escape_html)
|
277
|
-
|
277
|
+
|
278
278
|
Filters.add('markdown', :maruku, :passive => true) do |content, config|
|
279
279
|
require 'maruku'
|
280
280
|
::Maruku.new(content).to_html
|
281
281
|
end
|
282
|
-
|
282
|
+
|
283
283
|
Filters.add('textile', :redcloth, :passive => true) do |content, config|
|
284
284
|
R18n::Utils.use_syck { require 'redcloth' }
|
285
285
|
::RedCloth.new(content).to_html
|