r18n-core 4.0.0 → 5.0.1

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.
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