r18n-core 4.0.0 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +398 -0
  3. data/README.md +23 -13
  4. data/lib/r18n-core.rb +10 -25
  5. data/lib/r18n-core/filter_list.rb +6 -3
  6. data/lib/r18n-core/filters.rb +21 -22
  7. data/lib/r18n-core/i18n.rb +9 -16
  8. data/lib/r18n-core/locale.rb +20 -21
  9. data/lib/r18n-core/locales/cy.rb +1 -1
  10. data/lib/r18n-core/locales/en-au.rb +1 -1
  11. data/lib/r18n-core/locales/en-gb.rb +1 -1
  12. data/lib/r18n-core/locales/en-us.rb +1 -1
  13. data/lib/r18n-core/locales/en.rb +2 -2
  14. data/lib/r18n-core/locales/es-cl.rb +1 -1
  15. data/lib/r18n-core/locales/es-us.rb +1 -1
  16. data/lib/r18n-core/locales/es.rb +2 -0
  17. data/lib/r18n-core/locales/fi.rb +2 -2
  18. data/lib/r18n-core/locales/fr.rb +3 -3
  19. data/lib/r18n-core/locales/it.rb +3 -3
  20. data/lib/r18n-core/locales/pt.rb +2 -0
  21. data/lib/r18n-core/locales/zh-cn.rb +1 -1
  22. data/lib/r18n-core/locales/zh-tw.rb +1 -1
  23. data/lib/r18n-core/locales/zh.rb +2 -0
  24. data/lib/r18n-core/translated.rb +4 -4
  25. data/lib/r18n-core/translated_string.rb +1 -6
  26. data/lib/r18n-core/translation.rb +1 -1
  27. data/lib/r18n-core/unsupported_locale.rb +2 -0
  28. data/lib/r18n-core/utils.rb +1 -1
  29. data/lib/r18n-core/version.rb +1 -1
  30. metadata +198 -89
  31. data/.rspec +0 -1
  32. data/Rakefile +0 -13
  33. data/r18n-core.gemspec +0 -29
  34. data/spec/filters_spec.rb +0 -327
  35. data/spec/i18n_spec.rb +0 -274
  36. data/spec/locale_spec.rb +0 -251
  37. data/spec/locales/af_spec.rb +0 -9
  38. data/spec/locales/cs_spec.rb +0 -23
  39. data/spec/locales/en-us_spec.rb +0 -28
  40. data/spec/locales/en_spec.rb +0 -13
  41. data/spec/locales/es-us_spec.rb +0 -11
  42. data/spec/locales/fa_spec.rb +0 -10
  43. data/spec/locales/fi_spec.rb +0 -9
  44. data/spec/locales/fr_spec.rb +0 -9
  45. data/spec/locales/hu_spec.rb +0 -19
  46. data/spec/locales/id_spec.rb +0 -23
  47. data/spec/locales/it_spec.rb +0 -10
  48. data/spec/locales/no_spec.rb +0 -9
  49. data/spec/locales/pl_spec.rb +0 -23
  50. data/spec/locales/ru_spec.rb +0 -23
  51. data/spec/locales/sk_spec.rb +0 -23
  52. data/spec/locales/th_spec.rb +0 -9
  53. data/spec/locales/vi_spec.rb +0 -9
  54. data/spec/r18n_spec.rb +0 -192
  55. data/spec/spec_helper.rb +0 -38
  56. data/spec/translated_spec.rb +0 -225
  57. data/spec/translation_spec.rb +0 -189
  58. data/spec/translations/extension/deep/en.yml +0 -1
  59. data/spec/translations/extension/en.yml +0 -2
  60. data/spec/translations/extension/notransl.yml +0 -1
  61. data/spec/translations/general/en.yml +0 -52
  62. data/spec/translations/general/nolocale.yml +0 -6
  63. data/spec/translations/general/ru.yml +0 -7
  64. data/spec/translations/two/en.yml +0 -2
  65. data/spec/translations/two/fr.yml +0 -0
  66. data/spec/translations/with_regions/en-US.yml +0 -0
  67. data/spec/translations/yaml/en-GB.yml +0 -1
  68. data/spec/translations/yaml/en-us.yml +0 -1
  69. data/spec/translations/yaml/en.yaml +0 -1
  70. data/spec/yaml_loader_spec.rb +0 -63
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --format documentation --colour --warnings --require spec_helper
data/Rakefile DELETED
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- Bundler::GemHelper.install_tasks
5
-
6
- require 'rspec/core/rake_task'
7
- RSpec::Core::RakeTask.new
8
- task default: :spec
9
-
10
- task :clobber_package do
11
- rm_rf 'pkg'
12
- end
13
- task clobber: [:clobber_package]
data/r18n-core.gemspec DELETED
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'lib/r18n-core/version'
4
-
5
- Gem::Specification.new do |s|
6
- s.platform = Gem::Platform::RUBY
7
- s.name = 'r18n-core'
8
- s.version = R18n::VERSION.dup
9
- s.date = Time.now.strftime('%Y-%m-%d')
10
-
11
- s.summary = 'I18n tool to translate your Ruby application.'
12
- s.description = <<-DESC
13
- R18n is a i18n tool to translate your Ruby application.
14
- It has nice Ruby-style syntax, filters, flexible locales, custom loaders,
15
- translation support for any classes, time and number localization, several
16
- user language support, agnostic core package with out-of-box support for
17
- Rails, Sinatra and desktop applications.
18
- DESC
19
-
20
- s.files = `git ls-files`.split("\n")
21
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
- s.extra_rdoc_files = ['README.md', 'LICENSE']
23
- s.require_path = 'lib'
24
-
25
- s.author = 'Andrey Sitnik'
26
- s.email = 'andrey@sitnik.ru'
27
- s.homepage = 'https://github.com/r18n/r18n'
28
- s.license = 'LGPL-3.0'
29
- end
data/spec/filters_spec.rb DELETED
@@ -1,327 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe R18n::Filters do
4
- before do
5
- @system = R18n::Filters.defined.values
6
- @enabled = R18n::Filters.defined.values.select(&:enabled?)
7
- @i18n = R18n::I18n.new('en', DIR)
8
- @i18n.reload!
9
- end
10
-
11
- after do
12
- R18n::Filters.defined.each_value do |filter|
13
- next if @system.include? filter
14
-
15
- R18n::Filters.delete(filter)
16
- end
17
-
18
- @enabled.each { |i| R18n::Filters.on(i) unless i.enabled? }
19
- (@system - @enabled).each { |i| R18n::Filters.off(i) if i.enabled? }
20
- end
21
-
22
- it 'adds new filter' do
23
- filter = R18n::Filters.add('my', :my_filter) { |i, _config| i }
24
-
25
- expect(filter).to be_kind_of(R18n::Filters::Filter)
26
- expect(filter.name).to eq(:my_filter)
27
- expect(filter.types).to eq(['my'])
28
- expect(filter).to be_enabled
29
-
30
- expect(R18n::Filters.defined).to have_key(:my_filter)
31
-
32
- @i18n.reload!
33
- expect(@i18n.my_filter).to eq('value')
34
- expect(@i18n.my_tree_filter).to eq('name' => 'value')
35
- end
36
-
37
- it 'adds filter for several types' do
38
- R18n::Filters.add(%w[my your]) { |i, _config| i + '1' }
39
- @i18n.reload!
40
- expect(@i18n.my_filter).to eq('value1')
41
- expect(@i18n.your_filter).to eq('another1')
42
- end
43
-
44
- it 'uses passive filters' do
45
- filter = double
46
- expect(filter).to receive(:process).twice.and_return(1)
47
-
48
- R18n::Filters.add('my', :passive, passive: true) { filter.process }
49
-
50
- expect(@i18n.my_filter).to eq('value')
51
- @i18n.reload!
52
-
53
- expect(@i18n.my_tree_filter).to eq(1)
54
- expect(@i18n.my_filter).to eq(1)
55
- expect(@i18n.my_filter).to eq(1)
56
- end
57
-
58
- it 'uses cascade filters' do
59
- R18n::Filters.add('my', :one) { |i, _config| i + '1' }
60
- R18n::Filters.add('my', :two) { |i, _config| i + '2' }
61
- R18n::Filters.add('my', :three, position: 0) { |i, _c| i + '3' }
62
- expect(@i18n.my_filter).to eq('value312')
63
- end
64
-
65
- it 'returns name for nameless filter' do
66
- R18n::Filters.instance_variable_set(:@last_auto_name, 0)
67
-
68
- expect(R18n::Filters.add('some').name).to eq(1)
69
- expect(R18n::Filters.add('some', position: 0).name).to eq(2)
70
-
71
- R18n::Filters.add('some', 3)
72
- expect(R18n::Filters.add('some').name).to eq(4)
73
- end
74
-
75
- it 'deletes filter by name' do
76
- R18n::Filters.add('my', :my_filter) { '1' }
77
- expect(@i18n.my_filter).to eq('1')
78
-
79
- R18n::Filters.delete(:my_filter)
80
- expect(R18n::Filters.defined).not_to have_key(:my_filter)
81
- expect(@i18n.my_filter).to eq('value')
82
- end
83
-
84
- it 'deletes filter by object' do
85
- filter = R18n::Filters.add('my') { '1' }
86
- expect(@i18n.my_filter).to eq('1')
87
-
88
- R18n::Filters.delete(filter)
89
- expect(R18n::Filters.defined).not_to have_key(filter.name)
90
- expect(@i18n.my_filter).to eq('value')
91
- end
92
-
93
- it 'uses global filters' do
94
- R18n::Filters.add(String) { |result, _config, a, b| result + a + b }
95
- R18n::Filters.add(String) { |result, _config| result + '!' }
96
-
97
- expect(@i18n.one('1', '2')).to eq('One12!')
98
- end
99
-
100
- it 'turns off filter' do
101
- R18n::Filters.add('my', :one) { |i, _config| i + '1' }
102
- R18n::Filters.add('my', :two) { |i, _config| i + '2' }
103
-
104
- R18n::Filters.off(:one)
105
- expect(R18n::Filters.defined[:one]).not_to be_enabled
106
- expect(@i18n.my_filter).to eq('value2')
107
-
108
- R18n::Filters.on(:one)
109
- expect(R18n::Filters.defined[:one]).to be_enabled
110
- expect(@i18n.my_filter).to eq('value12')
111
- end
112
-
113
- it 'sends config to filter' do
114
- R18n::Filters.add('my') do |_i, config|
115
- config[:secret_value] = 1
116
- config
117
- end
118
- expect(@i18n.my_filter[:locale]).to eq(@i18n.locale)
119
- expect(@i18n.my_filter[:path]).to eq('my_filter')
120
- expect(@i18n.my_filter[:secret_value]).to eq(1)
121
- expect(@i18n.my_filter[:unknown_value]).to be_nil
122
- end
123
-
124
- it 'sets path in config' do
125
- R18n::Filters.add(String) do |_i, config|
126
- config[:path]
127
- end
128
-
129
- expect(@i18n.in.another.level).to eq('in.another.level')
130
- end
131
-
132
- it 'returns translated string after filters' do
133
- R18n::Filters.add(String) { |i, _config| i + '1' }
134
-
135
- expect(@i18n.one).to be_kind_of(R18n::TranslatedString)
136
- expect(@i18n.one.path).to eq('one')
137
- expect(@i18n.one.locale).to eq(R18n.locale('en'))
138
- end
139
-
140
- it 'uses one config for cascade filters' do
141
- R18n::Filters.add('my') { |_content, config| config[:new_secret] ? 2 : 1 }
142
- expect(@i18n.my_filter).to eq(1)
143
-
144
- R18n::Filters.add('my', :second, position: 0) do |content, config|
145
- config[:new_secret] = true
146
- content
147
- end
148
- expect(@i18n.my_filter).to eq(2)
149
- end
150
-
151
- it 'sends parameters to filter' do
152
- R18n::Filters.add('my') { |i, _config, a, b| "#{i}#{a}#{b}" }
153
- expect(@i18n['my_filter', 1, 2]).to eq('value12')
154
- expect(@i18n.my_filter(1, 2)).to eq('value12')
155
- end
156
-
157
- it 'pluralizes translation' do
158
- expect(@i18n.comments(0, 'article')).to eq('no comments for article')
159
- expect(@i18n.comments(1, 'article')).to eq('one comment for article')
160
- expect(@i18n.comments(5, 'article')).to eq('5 comments for article')
161
-
162
- expect(@i18n.files(0)).to eq('0 files')
163
- expect(@i18n.files(-5.5)).to eq('−5.5 files')
164
- expect(@i18n.files(5000)).to eq('5,000 files')
165
- end
166
-
167
- it "doesn't pluralize without first numeric parameter" do
168
- expect(@i18n.files).to be_kind_of(R18n::UnpluralizetedTranslation)
169
- expect(@i18n.files('')).to be_kind_of(R18n::UnpluralizetedTranslation)
170
- expect(@i18n.files[1]).to eq('1 file')
171
- expect(@i18n.files.n(5)).to eq('5 files')
172
- end
173
-
174
- it 'converts first float parameter to number' do
175
- expect(@i18n.files(1.2)).to eq('1 file')
176
- end
177
-
178
- it 'pluralizes translation without locale' do
179
- i18n = R18n::I18n.new('nolocale', DIR)
180
- expect(i18n.entries(1)).to eq('ONE')
181
- expect(i18n.entries(5)).to eq('N')
182
- end
183
-
184
- it 'cans use params in translation' do
185
- expect(@i18n.params(-1, 2)).to eq('Is −1 between −1 and 2?')
186
- end
187
-
188
- it "substitutes '%2' as param but not value of second param" do
189
- expect(@i18n.params('%2 FIRST', 'SECOND')).to eq(
190
- 'Is %2 FIRST between %2 FIRST and SECOND?'
191
- )
192
- end
193
-
194
- # rubocop:disable Style/FormatStringToken
195
- it 'interpolates named variables' do
196
- R18n::Filters.off(:named_variables)
197
- expect(@i18n.echo(value: 'R18n')).to eq 'Value is %{value}'
198
-
199
- R18n::Filters.on(:named_variables)
200
- expect(@i18n.echo(value: 'R18n')).to eq 'Value is R18n'
201
- expect(@i18n.echo(value: -5.5)).to eq 'Value is −5.5'
202
- expect(@i18n.echo(value: 5000)).to eq 'Value is 5,000'
203
- expect(@i18n.echo(value: '<b>')).to eq 'Value is <b>'
204
- expect(@i18n.echo).to eq 'Value is %{value}'
205
-
206
- expect(@i18n.echo2(value: 'R18n')).to eq 'Value2 is R18n'
207
- expect(@i18n.echo2).to eq 'Value2 is {{value}}'
208
- end
209
- # rubocop:enable Style/FormatStringToken
210
-
211
- it 'formats untranslated' do
212
- expect(@i18n.in.not.to_s).to eq('in.[not]')
213
- expect(@i18n.in.not.to_str).to eq('in.[not]')
214
-
215
- expect(@i18n.one.not_exists.to_s).to eq('one.[not_exists]')
216
-
217
- R18n::Filters.off(:untranslated)
218
- expect(@i18n.in.not.to_s).to eq('in.not')
219
-
220
- R18n::Filters.add(R18n::Untranslated) do |_v, _c, trans, untrans, path|
221
- "#{path} #{trans}[#{untrans}]"
222
- end
223
- expect(@i18n.in.not.to_s).to eq('in.not in.[not]')
224
- end
225
-
226
- it 'formats translation path' do
227
- expect(@i18n.in.another.to_s).to eq('in.another[]')
228
-
229
- R18n::Filters.off(:untranslated)
230
- expect(@i18n.in.another.to_s).to eq('in.another')
231
-
232
- R18n::Filters.add(R18n::Untranslated) do |_v, _c, trans, untrans, path|
233
- "#{path} #{trans}[#{untrans}]"
234
- end
235
- expect(@i18n.in.another.to_s).to eq('in.another in.another[]')
236
- end
237
-
238
- it 'formats untranslated for web' do
239
- R18n::Filters.off(:untranslated)
240
- R18n::Filters.on(:untranslated_html)
241
- expect(@i18n.in.not.to_s).to eq('in.<span style="color: red">[not]</span>')
242
- expect(@i18n['<b>'].to_s).to eq(
243
- '<span style="color: red">[&lt;b&gt;]</span>'
244
- )
245
- end
246
-
247
- it 'allows to set custom filters' do
248
- R18n::Filters.add(R18n::Untranslated, :a) { |v, _c| "a #{v}" }
249
- R18n::Filters.off(:a)
250
-
251
- html = R18n::I18n.new(
252
- 'en', DIR,
253
- off_filters: :untranslated, on_filters: %i[untranslated_html a]
254
- )
255
- expect(html.in.not.to_s).to eq('a in.<span style="color: red">[not]</span>')
256
- end
257
-
258
- it 'has filter for escape HTML' do
259
- expect(@i18n.html).to eq(
260
- '&lt;script&gt;true &amp;&amp; false&lt;/script&gt;'
261
- )
262
- end
263
-
264
- it 'has disabled global filter for escape HTML' do
265
- expect(@i18n.greater('true')).to eq('1 < 2 is true')
266
-
267
- R18n::Filters.on(:global_escape_html)
268
- @i18n.reload!
269
- expect(@i18n.greater('true')).to eq('1 &lt; 2 is true')
270
- expect(@i18n.html).to eq(
271
- '&lt;script&gt;true &amp;&amp; false&lt;/script&gt;'
272
- )
273
- end
274
-
275
- it 'has filter to disable global HTML escape' do
276
- expect(@i18n.no_escape).to eq('<b>Warning</b>')
277
-
278
- R18n::Filters.on(:global_escape_html)
279
- @i18n.reload!
280
- expect(@i18n.no_escape).to eq('<b>Warning</b>')
281
- end
282
-
283
- it 'has Markdown filter' do
284
- expect(@i18n.markdown.simple).to eq("<p><strong>Hi!</strong></p>\n")
285
- end
286
-
287
- it 'has Textile filter' do
288
- expect(@i18n.textile.simple).to eq('<p><em>Hi!</em></p>')
289
- end
290
-
291
- it 'HTML escapes before Markdown and Textile filters' do
292
- expect(@i18n.markdown.html).to eq("<p><strong>Hi!</strong> <br /></p>\n")
293
- expect(@i18n.textile.html).to eq('<p><em>Hi!</em><br /></p>')
294
-
295
- R18n::Filters.on(:global_escape_html)
296
- @i18n.reload!
297
- expect(@i18n.markdown.html).to eq(
298
- "<p><strong>Hi!</strong> &lt;br /&gt;</p>\n"
299
- )
300
- expect(@i18n.textile.html).to eq(
301
- '<p><em>Hi!</em>&lt;br /&gt;</p>'
302
- )
303
- end
304
-
305
- it 'allows to listen filters adding' do
306
- expect(R18n::Filters.listen do
307
- R18n::Filters.add(String, :a) {}
308
- end).to eq([R18n::Filters.defined[:a]])
309
- end
310
-
311
- it 'escapes variables if ActiveSupport is loaded' do
312
- expect(@i18n.escape_params('<br>')).to eq('<b><br></b>')
313
-
314
- require 'active_support'
315
-
316
- expect(@i18n.escape_params('<br>')).to eq('<b>&lt;br&gt;</b>')
317
-
318
- R18n::Filters.on(:global_escape_html)
319
- @i18n.reload!
320
-
321
- expect(@i18n.greater('<b>'.html_safe)).to eq('1 &lt; 2 is <b>')
322
-
323
- R18n::Filters.on(:named_variables)
324
-
325
- expect(@i18n.echo(value: '<b>')).to eq 'Value is &lt;b&gt;'
326
- end
327
- end
data/spec/i18n_spec.rb DELETED
@@ -1,274 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe R18n::I18n do
4
- before do
5
- @extension_places = R18n.extension_places.clone
6
- end
7
-
8
- after do
9
- R18n::I18n.default = 'en'
10
- R18n.default_loader = R18n::Loader::YAML
11
- R18n.extension_places = @extension_places
12
- end
13
-
14
- it 'parses HTTP_ACCEPT_LANGUAGE' do
15
- expect(R18n::I18n.parse_http(nil)).to eq([])
16
- expect(R18n::I18n.parse_http('')).to eq([])
17
- expect(R18n::I18n.parse_http('ru,en;q=0.9')).to eq(%w[ru en])
18
- expect(R18n::I18n.parse_http('ru;q=0.8,en;q=0.9')).to eq(%w[en ru])
19
- end
20
-
21
- it 'has default locale' do
22
- R18n::I18n.default = 'ru'
23
- expect(R18n::I18n.default).to eq('ru')
24
- end
25
-
26
- it 'loads locales' do
27
- i18n = R18n::I18n.new('en', DIR)
28
- expect(i18n.locales).to eq([R18n.locale('en')])
29
-
30
- i18n = R18n::I18n.new(%w[ru nolocale-DL], DIR)
31
- expect(i18n.locales).to eq([
32
- R18n.locale('ru'),
33
- R18n::UnsupportedLocale.new('nolocale-DL'),
34
- R18n::UnsupportedLocale.new('nolocale'),
35
- R18n.locale('en')
36
- ])
37
- end
38
-
39
- it 'returns translations loaders' do
40
- i18n = R18n::I18n.new('en', DIR)
41
- expect(i18n.translation_places).to eq([R18n::Loader::YAML.new(DIR)])
42
- end
43
-
44
- it 'loads translations by loader' do
45
- loader = Class.new do
46
- def available
47
- [R18n.locale('en')]
48
- end
49
-
50
- def load(_locale)
51
- { 'custom' => 'Custom' }
52
- end
53
- end
54
- expect(R18n::I18n.new('en', loader.new).custom).to eq('Custom')
55
- end
56
-
57
- it 'passes parameters to default loader' do
58
- loader = Class.new do
59
- def initialize(param)
60
- @param = param
61
- end
62
-
63
- def available
64
- [R18n.locale('en')]
65
- end
66
-
67
- def load(_locale)
68
- { 'custom' => @param }
69
- end
70
- end
71
- R18n.default_loader = loader
72
- expect(R18n::I18n.new('en', 'default').custom).to eq('default')
73
- end
74
-
75
- it 'loads translations' do
76
- i18n = R18n::I18n.new(%w[ru en], DIR)
77
- expect(i18n.one).to eq('Один')
78
- expect(i18n[:one]).to eq('Один')
79
- expect(i18n['one']).to eq('Один')
80
- expect(i18n.only.english).to eq('Only in English')
81
- end
82
-
83
- it 'loads translations from several dirs' do
84
- i18n = R18n::I18n.new(%w[nolocale en], [TWO, DIR])
85
- expect(i18n.in.two).to eq('Two')
86
- expect(i18n.in.another.level).to eq('Hierarchical')
87
- end
88
-
89
- it 'uses extension places' do
90
- R18n.extension_places << EXT
91
-
92
- i18n = R18n::I18n.new('en', DIR)
93
- expect(i18n.ext).to eq('Extension')
94
- expect(i18n.one).to eq('One')
95
- end
96
-
97
- it "doesn't use extension without app translations with same locale" do
98
- R18n.extension_places << EXT
99
-
100
- i18n = R18n::I18n.new(%w[notransl en], DIR)
101
- expect(i18n.ext).to eq('Extension')
102
- end
103
-
104
- it 'ignores case on loading' do
105
- i18n = R18n::I18n.new('nolocale', [DIR])
106
- expect(i18n.one).to eq('ONE')
107
-
108
- i18n = R18n::I18n.new('nolocale', [DIR])
109
- expect(i18n.one).to eq('ONE')
110
- end
111
-
112
- it 'loads default translation' do
113
- i18n = R18n::I18n.new('nolocale', DIR)
114
- expect(i18n.one).to eq('ONE')
115
- expect(i18n.two).to eq('Two')
116
- end
117
-
118
- it 'loads sublocales for first locale' do
119
- R18n::I18n.default = 'notransl'
120
-
121
- i18n = R18n::I18n.new('ru', DIR)
122
- expect(i18n.one).to eq('Один')
123
- expect(i18n.two).to eq('Two')
124
- end
125
-
126
- it 'loads base translations from parent locale' do
127
- i18n = R18n::I18n.new('en-US', File.join(TRANSLATIONS, 'with_regions'))
128
- expect(i18n.save).to eq('Save')
129
- end
130
-
131
- it 'returns available translations' do
132
- i18n = R18n::I18n.new('en', DIR)
133
- expect(i18n.available_locales).to match_array([
134
- R18n.locale('nolocale'),
135
- R18n.locale('ru'),
136
- R18n.locale('en')
137
- ])
138
- end
139
-
140
- it 'caches translations' do
141
- counter = CounterLoader.new('en')
142
-
143
- R18n::I18n.new('en', counter)
144
- expect(counter.loaded).to eq(1)
145
-
146
- R18n::I18n.new('en', counter)
147
- expect(counter.loaded).to eq(1)
148
-
149
- R18n.clear_cache!
150
- R18n::I18n.new('en', counter)
151
- expect(counter.loaded).to eq(2)
152
- end
153
-
154
- it "doesn't clear cache when custom filters are specified" do
155
- counter = CounterLoader.new('en')
156
-
157
- R18n::I18n.new(
158
- 'en', counter, off_filters: :untranslated, on_filters: :untranslated_html
159
- )
160
- expect(counter.loaded).to eq(1)
161
-
162
- R18n::I18n.new(
163
- 'en', counter, off_filters: :untranslated, on_filters: :untranslated_html
164
- )
165
- expect(counter.loaded).to eq(1)
166
- end
167
-
168
- it 'caches translations by used locales' do
169
- counter = CounterLoader.new('en', 'ru')
170
-
171
- R18n::I18n.new('en', counter)
172
- expect(counter.loaded).to eq(1)
173
-
174
- R18n::I18n.new(%w[en fr], counter)
175
- expect(counter.loaded).to eq(1)
176
-
177
- R18n::I18n.new(%w[en ru], counter)
178
- expect(counter.loaded).to eq(3)
179
-
180
- R18n::I18n.new(%w[ru en], counter)
181
- expect(counter.loaded).to eq(5)
182
- end
183
-
184
- it 'caches translations by places' do
185
- counter = CounterLoader.new('en', 'ru')
186
-
187
- R18n::I18n.new('en', counter)
188
- expect(counter.loaded).to eq(1)
189
-
190
- R18n::I18n.new('en', [counter, DIR])
191
- expect(counter.loaded).to eq(2)
192
-
193
- R18n.extension_places << EXT
194
- R18n::I18n.new('en', counter)
195
- expect(counter.loaded).to eq(3)
196
-
197
- same = CounterLoader.new('en', 'ru')
198
- R18n::I18n.new('en', same)
199
- expect(same.loaded).to eq(0)
200
-
201
- different = CounterLoader.new('en', 'fr')
202
- R18n::I18n.new('en', different)
203
- expect(different.loaded).to eq(1)
204
- end
205
-
206
- it 'reloads translations' do
207
- loader = Class.new do
208
- def available
209
- [R18n.locale('en')]
210
- end
211
-
212
- def load(_locale)
213
- @answer ||= 0
214
- @answer += 1
215
- { 'one' => @answer }
216
- end
217
- end
218
-
219
- i18n = R18n::I18n.new('en', loader.new)
220
- expect(i18n.one).to eq(1)
221
-
222
- i18n.reload!
223
- expect(i18n.one).to eq(2)
224
- end
225
-
226
- it 'returns translations' do
227
- i18n = R18n::I18n.new('en', DIR)
228
- expect(i18n.t).to be_kind_of(R18n::Translation)
229
- expect(i18n.t.one).to eq('One')
230
- end
231
-
232
- it 'returns first locale with locale file' do
233
- i18n = R18n::I18n.new(%w[notransl nolocale ru en], DIR)
234
- expect(i18n.locale).to eq(R18n.locale('nolocale'))
235
- expect(i18n.locale.base).to eq(R18n.locale('ru'))
236
- end
237
-
238
- it 'localizes objects' do
239
- i18n = R18n::I18n.new('ru')
240
-
241
- expect(i18n.l(-123_456_789)).to eq('−123 456 789')
242
- expect(i18n.l(-12_345.67)).to eq('−12 345,67')
243
-
244
- time = Time.utc(2014, 5, 6, 7, 8, 9)
245
- expect(i18n.l(time, '%A'))
246
- .to eq('Вторник')
247
- expect(i18n.l(time, :month))
248
- .to eq('Май')
249
- expect(i18n.l(time, :standard))
250
- .to eq('06.05.2014 07:08')
251
- expect(i18n.l(time, :standard, with_seconds: true))
252
- .to eq('06.05.2014 07:08:09')
253
- expect(i18n.l(time, :full))
254
- .to eq('6 мая 2014 07:08')
255
- expect(i18n.l(time, :full, with_seconds: true))
256
- .to eq('6 мая 2014 07:08:09')
257
-
258
- expect(i18n.l(Date.new(0))).to eq('01.01.0000')
259
- end
260
-
261
- it 'returns marshalizable values' do
262
- i18n = R18n::I18n.new(
263
- 'en', DIR, off_filters: :untranslated, on_filters: :untranslated_html
264
- )
265
- demarsh = Marshal.load(Marshal.dump(i18n.t.one))
266
-
267
- expect(i18n.t.one).to eq(demarsh)
268
- expect(i18n.t.one.path).to eq(demarsh.path)
269
- expect(i18n.t.one.locale).to eq(demarsh.locale)
270
-
271
- demarsh = Marshal.load(Marshal.dump(i18n.t.no_translation))
272
- expect(i18n.t.no_translation).to eq(demarsh)
273
- end
274
- end