fast_gettext 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,8 +13,7 @@ module FastGettext
13
13
  [:available_locales, :_locale, :text_domain, :pluralisation_rule].each do |method_name|
14
14
  key = "fast_gettext_#{method_name}".to_sym
15
15
  define_method "#{method_name}=" do |value|
16
- Thread.current[key]=value
17
- update_current_cache
16
+ update_current_cache if Thread.current[key] != Thread.current[key]=value
18
17
  end
19
18
  end
20
19
 
@@ -17,15 +17,15 @@ module FastGettext
17
17
  klas.extend self
18
18
  end
19
19
 
20
- def _(key)
21
- FastGettext.cached_find(key) or key
20
+ def _(key, &block)
21
+ FastGettext.cached_find(key) or (block ? block.call : key)
22
22
  end
23
23
 
24
24
  #translate pluralized
25
25
  # some languages have up to 4 plural forms...
26
26
  # n_(singular, plural, plural form 2, ..., count)
27
27
  # n_('apple','apples',3)
28
- def n_(*keys)
28
+ def n_(*keys, &block)
29
29
  count = keys.pop
30
30
  translations = FastGettext.cached_plural_find(*keys)
31
31
 
@@ -38,15 +38,15 @@ module FastGettext
38
38
  elsif keys[selected]
39
39
  _(keys[selected])
40
40
  else
41
- keys.last
41
+ block ? block.call : keys.last
42
42
  end
43
43
  end
44
44
 
45
45
  #translate, but discard namespace if nothing was found
46
46
  # Car|Tire -> Tire if no translation could be found
47
- def s_(key,separator=nil)
47
+ def s_(key, separator=nil, &block)
48
48
  translation = FastGettext.cached_find(key) and return translation
49
- key.split(separator||NAMESPACE_SEPARATOR).last
49
+ block ? block.call : key.split(separator||NAMESPACE_SEPARATOR).last
50
50
  end
51
51
 
52
52
  #tell gettext: this string need translation (will be found during parsing)
@@ -59,8 +59,92 @@ module FastGettext
59
59
  keys
60
60
  end
61
61
 
62
- def ns_(*args)
63
- n_(*args).split(NAMESPACE_SEPARATOR).last
62
+ def ns_(*args, &block)
63
+ translation = n_(*args, &block)
64
+ # block is called once again to compare result
65
+ block && translation == block.call ? translation : translation.split(NAMESPACE_SEPARATOR).last
66
+ end
67
+ end
68
+
69
+ # this module should be included for multi-domain support
70
+ module TranslationMultidomain
71
+ extend self
72
+
73
+ #make it usable in class definition, e.g.
74
+ # class Y
75
+ # include FastGettext::TranslationMultidomain
76
+ # @@x = d_('domain', 'y')
77
+ # end
78
+ def self.included(klas) #:nodoc:
79
+ klas.extend self
80
+ end
81
+
82
+ # helper block for changing domains
83
+ def _in_domain domain
84
+ old_domain = FastGettext.text_domain
85
+ FastGettext.text_domain = domain
86
+ yield if block_given?
87
+ ensure
88
+ FastGettext.text_domain = old_domain
89
+ end
90
+
91
+ # gettext functions to translate in the context of given domain
92
+ def d_(domain, key, &block)
93
+ _in_domain domain do
94
+ FastGettext::Translation._(key, &block)
95
+ end
96
+ end
97
+
98
+ def dn_(domain, *keys, &block)
99
+ _in_domain domain do
100
+ FastGettext::Translation.n_(*keys, &block)
101
+ end
102
+ end
103
+
104
+ def ds_(domain, key, separator=nil, &block)
105
+ _in_domain domain do
106
+ FastGettext::Translation.s_(key, separator, &block)
107
+ end
108
+ end
109
+
110
+ def dns_(domain, *keys, &block)
111
+ _in_domain domain do
112
+ FastGettext::Translation.ns_(*keys, &block)
113
+ end
114
+ end
115
+
116
+ # gettext functions to translate in the context of any domain
117
+ # (note: if mutiple domains contains key, random translation is returned)
118
+ def D_(key)
119
+ FastGettext.translation_repositories.each_key do |domain|
120
+ result = FastGettext::TranslationMultidomain.d_(domain, key) {nil}
121
+ return result unless result.nil?
122
+ end
123
+ key
124
+ end
125
+
126
+ def Dn_(*keys)
127
+ FastGettext.translation_repositories.each_key do |domain|
128
+ result = FastGettext::TranslationMultidomain.dn_(domain, *keys) {nil}
129
+ return result unless result.nil?
130
+ end
131
+ keys[-3].split(keys[-2]||NAMESPACE_SEPARATOR).last
132
+ end
133
+
134
+ def Ds_(key, separator=nil)
135
+ FastGettext.translation_repositories.each_key do |domain|
136
+ result = FastGettext::TranslationMultidomain.ds_(domain, key, separator) {nil}
137
+ return result unless result.nil?
138
+ end
139
+ key.split(separator||NAMESPACE_SEPARATOR).last
140
+ end
141
+
142
+ def Dns_(*keys)
143
+ FastGettext.translation_repositories.each_key do |domain|
144
+ result = FastGettext::TranslationMultidomain.dns_(domain, *keys) {nil}
145
+ return result unless result.nil?
146
+ end
147
+ keys[-2].split(NAMESPACE_SEPARATOR).last
64
148
  end
65
149
  end
66
150
  end
@@ -1,3 +1,5 @@
1
+ require "protected_attributes" if ActiveRecord::VERSION::MAJOR >= 4
2
+
1
3
  class TranslationKey < ActiveRecord::Base
2
4
  has_many :translations, :class_name => 'TranslationText', :dependent => :destroy
3
5
 
@@ -17,7 +19,13 @@ class TranslationKey < ActiveRecord::Base
17
19
  end
18
20
 
19
21
  def self.available_locales
20
- @@available_locales ||= TranslationText.count(:group=>:locale).keys.sort
22
+ @@available_locales ||= begin
23
+ if ActiveRecord::VERSION::MAJOR >= 3
24
+ TranslationText.group(:locale).count
25
+ else
26
+ TranslationText.count(:group=>:locale)
27
+ end.keys.sort
28
+ end
21
29
  end
22
30
 
23
31
  protected
@@ -1,3 +1,5 @@
1
+ require "protected_attributes" if ActiveRecord::VERSION::MAJOR >= 4
2
+
1
3
  class TranslationText < ActiveRecord::Base
2
4
  belongs_to :translation_key, :class_name => 'TranslationKey'
3
5
  validates_presence_of :locale
@@ -1,3 +1,3 @@
1
1
  module FastGettext
2
- VERSION = Version = '0.7.1'
2
+ VERSION = Version = '0.8.0'
3
3
  end
@@ -61,7 +61,7 @@ describe 'Storage' do
61
61
 
62
62
  describe :pluralisation_rule do
63
63
  it "defaults to singular-if-1 when it is not set" do
64
- stub!(:current_repository).and_return mock('',:pluralisation_rule=>nil)
64
+ should_receive(:current_repository).at_least(1).and_return double(:pluralisation_rule => nil)
65
65
  self.pluralisation_rule = nil
66
66
  pluralisation_rule.call(1).should == false
67
67
  pluralisation_rule.call(0).should == true
@@ -256,8 +256,8 @@ describe 'Storage' do
256
256
  FastGettext.text_domain = 'xxx'
257
257
  FastGettext.available_locales = ['de','en']
258
258
  FastGettext.locale = 'de'
259
- FastGettext.current_repository.stub!(:"[]").with('abc').and_return 'old'
260
- FastGettext.current_repository.stub!(:"[]").with('unfound').and_return nil
259
+ FastGettext.current_repository.stub(:"[]").with('abc').and_return 'old'
260
+ FastGettext.current_repository.stub(:"[]").with('unfound').and_return nil
261
261
  FastGettext._('abc')
262
262
  FastGettext._('unfound')
263
263
  FastGettext.locale = 'en'
@@ -333,7 +333,6 @@ describe 'Storage' do
333
333
 
334
334
  it "does not overwrite an existing cache value" do
335
335
  current_cache['xxx']='xxx'
336
- stub!(:current_repository).and_return 'xxx'=>'1'
337
336
  key_exist?('xxx')
338
337
  current_cache['xxx'].should == 'xxx'
339
338
  end
@@ -36,9 +36,9 @@ describe 'FastGettext::TranslationRepository::Chain' do
36
36
  describe "filled chain" do
37
37
  before do
38
38
  @one = MockRepo.new
39
- @one.stub!(:singular).with('xx').and_return 'one'
39
+ @one.stub(:singular).with('xx').and_return 'one'
40
40
  @two = MockRepo.new
41
- @two.stub!(:singular).with('xx').and_return 'two'
41
+ @two.stub(:singular).with('xx').and_return 'two'
42
42
  @rep = FastGettext::TranslationRepository.build('chain', :chain=>[@one, @two], :type=>:chain)
43
43
  end
44
44
 
@@ -31,11 +31,11 @@ describe 'FastGettext::TranslationRepository::Mo' do
31
31
  it "can reload" do
32
32
  FastGettext.locale = 'de'
33
33
 
34
- @rep['Untranslated'].should be_nil
34
+ @rep['Untranslated and translated in test2'].should be_nil
35
35
 
36
36
  @rep.reload
37
37
 
38
- @rep['Untranslated'].should == 'Translated'
38
+ @rep['Untranslated and translated in test2'].should == 'Translated'
39
39
  end
40
40
 
41
41
  it "returns true" do
@@ -51,6 +51,8 @@ describe 'FastGettext::TranslationRepository::Mo' do
51
51
  end
52
52
 
53
53
  it "can work in SAFE mode" do
54
- `ruby spec/cases/safe_mode_can_handle_locales.rb 2>&1`.should == 'true'
54
+ pending_if RUBY_VERSION > "2.0" do
55
+ `ruby spec/cases/safe_mode_can_handle_locales.rb 2>&1`.should == 'true'
56
+ end
55
57
  end
56
58
  end
@@ -61,7 +61,7 @@ describe 'FastGettext::TranslationRepository::Yaml' do
61
61
  end
62
62
 
63
63
  it "can be used to translate plural forms" do
64
- FastGettext.stub!(:current_repository).and_return @rep
64
+ FastGettext.stub(:current_repository).and_return @rep
65
65
  FastGettext.n_('cars.axis','cars.axis',2).should == 'Achsen'
66
66
  FastGettext.n_('cars.axis',2).should == 'Achsen'
67
67
  FastGettext.n_('cars.axis',1).should == 'Achse'
@@ -69,8 +69,8 @@ describe 'FastGettext::TranslationRepository::Yaml' do
69
69
 
70
70
  4.times do |i|
71
71
  it "can be used to do wanky pluralisation rules #{i}" do
72
- FastGettext.stub!(:current_repository).and_return @rep
73
- @rep.stub!(:pluralisation_rule).and_return lambda{|x| i}
72
+ FastGettext.stub(:current_repository).and_return @rep
73
+ @rep.stub(:pluralisation_rule).and_return lambda{|x| i}
74
74
  FastGettext.n_('cars.silly',1).should == i.to_s # cars.silly translations are 0,1,2,3
75
75
  end
76
76
  end
@@ -2,6 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe FastGettext::Translation do
4
4
  include FastGettext::Translation
5
+ include FastGettext::TranslationMultidomain
5
6
 
6
7
  before do
7
8
  default_setup
@@ -42,6 +43,14 @@ describe FastGettext::Translation do
42
43
  it "does not return the gettext meta information" do
43
44
  _('').should == ''
44
45
  end
46
+
47
+ it "returns nil when specified" do
48
+ _('not found'){nil}.should be_nil
49
+ end
50
+
51
+ it "returns block when specified" do
52
+ _('not found'){:block}.should == :block
53
+ end
45
54
  end
46
55
 
47
56
  describe :n_ do
@@ -85,6 +94,10 @@ describe FastGettext::Translation do
85
94
  FastGettext.pluralisation_rule = lambda{|x|4}
86
95
  n_('Apple','Apples',2).should == 'Apples'
87
96
  end
97
+
98
+ it "returns block when specified" do
99
+ n_('not found'){:block}.should == :block
100
+ end
88
101
  end
89
102
 
90
103
  describe :s_ do
@@ -99,6 +112,10 @@ describe FastGettext::Translation do
99
112
  it "can use a custom seperator" do
100
113
  s_("XXX/not found",'/').should == "not found"
101
114
  end
115
+
116
+ it "returns block when specified" do
117
+ s_('not found'){:block}.should == :block
118
+ end
102
119
  end
103
120
 
104
121
  describe :N_ do
@@ -117,13 +134,181 @@ describe FastGettext::Translation do
117
134
  it "translates whith namespace" do
118
135
  ns_('Fruit|Apple','Fruit|Apples',2).should == 'Apples'
119
136
  end
137
+
138
+ it "returns block when specified" do
139
+ ns_('not found'){:block}.should == :block
140
+ ns_('not found'){nil}.should be_nil
141
+ end
120
142
  end
121
143
 
144
+ describe :multi_domain do
145
+ before do
146
+ setup_extra_domain
147
+ end
148
+
149
+ describe :_in_domain do
150
+ it "changes domain via in_domain" do
151
+ Thread.current[:fast_gettext_text_domain].should == "test"
152
+ _in_domain "fake" do
153
+ Thread.current[:fast_gettext_text_domain].should == "fake"
154
+ end
155
+ Thread.current[:fast_gettext_text_domain].should == "test"
156
+ end
157
+ end
158
+
159
+ describe :d_ do
160
+ it "translates simple text" do
161
+ d_('test', 'car').should == 'Auto'
162
+ end
163
+
164
+ it "translates simple text in different domain" do
165
+ d_('test2', 'car').should == 'Auto 2'
166
+ end
167
+
168
+ it "translates simple text in different domain one transaction" do
169
+ d_('test', 'car').should == 'Auto'
170
+ d_('test2', 'car').should == 'Auto 2'
171
+ end
172
+
173
+ it "returns the original string if its translation is blank" do
174
+ d_('test', 'Untranslated').should == 'Untranslated'
175
+ end
176
+
177
+ it "sets text domain back to previous one" do
178
+ old_domain = FastGettext.text_domain
179
+ d_('test2', 'car').should == 'Auto 2'
180
+ FastGettext.text_domain.should == old_domain
181
+ end
182
+
183
+ it "returns appropriate key if translation is not found in a domain" do
184
+ FastGettext.translation_repositories['fake'] = {}
185
+ d_('fake', 'car').should == 'car'
186
+ end
187
+ end
188
+
189
+ describe :dn_ do
190
+ before do
191
+ FastGettext.pluralisation_rule = nil
192
+ end
193
+
194
+ it "translates pluralized" do
195
+ dn_('test', 'Axis','Axis',1).should == 'Achse'
196
+ dn_('test2', 'Axis','Axis',1).should == 'Achse 2'
197
+ end
198
+
199
+ it "returns a simple translation when no combined was found" do
200
+ dn_('test', 'Axis','NOTFOUNDs',1).should == 'Achse'
201
+ dn_('test2', 'Axis','NOTFOUNDs',1).should == 'Achse 2'
202
+ end
203
+
204
+ it "returns the appropriate key if no translation was found" do
205
+ dn_('test', 'NOTFOUND','NOTFOUNDs',1).should == 'NOTFOUND'
206
+ dn_('test', 'NOTFOUND','NOTFOUNDs',2).should == 'NOTFOUNDs'
207
+ end
208
+
209
+ it "returns the last key when no translation was found and keys where to short" do
210
+ FastGettext.pluralisation_rule = lambda{|x|4}
211
+ dn_('test', 'Apple','Apples',2).should == 'Apples'
212
+ end
213
+ end
214
+
215
+ describe :ds_ do
216
+ it "translates simple text" do
217
+ ds_('test2', 'car').should == 'Auto 2'
218
+ ds_('test', 'car').should == 'Auto'
219
+ end
220
+
221
+ it "returns cleaned key if a translation was not found" do
222
+ ds_('test2', "XXX|not found").should == "not found"
223
+ end
224
+
225
+ it "can use a custom seperator" do
226
+ ds_('test2', "XXX/not found",'/').should == "not found"
227
+ end
228
+ end
229
+
230
+ describe :dns_ do
231
+ it "translates whith namespace" do
232
+ dns_('test', 'Fruit|Apple','Fruit|Apples',2).should == 'Apples'
233
+ dns_('test2', 'Fruit|Apple','Fruit|Apples',2).should == 'Apples'
234
+ end
235
+ end
236
+ end
237
+
238
+ describe :multidomain_all do
239
+ before do
240
+ setup_extra_domain
241
+ end
242
+
243
+ describe :D_ do
244
+ it "translates simple text" do
245
+ D_('not found').should == 'not found'
246
+ D_('only in test2 domain').should == 'nur in test2 Domain'
247
+ end
248
+
249
+ it "returns translation from random domain" do
250
+ D_('car').should match('(Auto|Auto 2)')
251
+ end
252
+
253
+ it "sets text domain back to previous one" do
254
+ old_domain = FastGettext.text_domain
255
+ D_('car').should == 'Auto'
256
+ FastGettext.text_domain.should == old_domain
257
+ end
258
+ end
259
+
260
+ describe :Dn_ do
261
+ before do
262
+ FastGettext.pluralisation_rule = nil
263
+ end
264
+
265
+ it "translates pluralized" do
266
+ Dn_('Axis','Axis',1).should match('(Achse|Achse 2)')
267
+ end
268
+
269
+ it "returns a simple translation when no combined was found" do
270
+ Dn_('Axis','NOTFOUNDs',1).should match('(Achse|Achse 2)')
271
+ end
272
+
273
+ it "returns the appropriate key if no translation was found" do
274
+ Dn_('NOTFOUND','NOTFOUNDs',1).should == 'NOTFOUND'
275
+ end
276
+
277
+ it "returns the last key when no translation was found and keys where to short" do
278
+ Dn_('Apple','Apples',2).should == 'Apples'
279
+ end
280
+ end
281
+
282
+ describe :Ds_ do
283
+ it "translates simple text" do
284
+ Ds_('car').should match('(Auto|Auto 2)')
285
+ end
286
+
287
+ it "returns cleaned key if a translation was not found" do
288
+ Ds_("XXX|not found").should == "not found"
289
+ end
290
+
291
+ it "can use a custom seperator" do
292
+ Ds_("XXX/not found",'/').should == "not found"
293
+ end
294
+ end
295
+
296
+ describe :Dns_ do
297
+ it "translates whith namespace" do
298
+ Dns_('Fruit|Apple','Fruit|Apples',1).should == 'Apple'
299
+ Dns_('Fruit|Apple','Fruit|Apples',2).should == 'Apples'
300
+ end
301
+
302
+ it "returns cleaned key if a translation was not found" do
303
+ Dns_("XXX|not found", "YYY|not found", 1).should == "not found"
304
+ Dns_("XXX|not found", "YYY|not found", 2).should == "not found"
305
+ end
306
+ end
307
+ end
122
308
 
123
309
  describe :caching do
124
310
  describe :cache_hit do
125
311
  before do
126
- FastGettext.translation_repositories.replace({})
127
312
  #singular cache keys
128
313
  FastGettext.current_cache['xxx'] = '1'
129
314
 
@@ -166,5 +351,13 @@ describe FastGettext::Translation do
166
351
  FastGettext.text_domain = 'test'
167
352
  _('car').should == 'Auto'
168
353
  end
354
+
355
+ it "caches different textdomains seperatly for d_" do
356
+ _('car').should == 'Auto'
357
+
358
+ FastGettext.translation_repositories['fake'] = {}
359
+ d_('fake', 'car').should == 'car'
360
+ d_('test','car').should == 'Auto'
361
+ end
169
362
  end
170
363
  end