r18n-core 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +1 -1
  3. data/ChangeLog.md +6 -1
  4. data/README.md +1 -20
  5. data/Rakefile +5 -3
  6. data/lib/r18n-core.rb +55 -55
  7. data/lib/r18n-core/filter_list.rb +34 -36
  8. data/lib/r18n-core/filters.rb +68 -51
  9. data/lib/r18n-core/helpers.rb +17 -17
  10. data/lib/r18n-core/i18n.rb +46 -39
  11. data/lib/r18n-core/locale.rb +79 -70
  12. data/lib/r18n-core/translated.rb +65 -66
  13. data/lib/r18n-core/translated_string.rb +24 -24
  14. data/lib/r18n-core/translation.rb +31 -30
  15. data/lib/r18n-core/unsupported_locale.rb +22 -24
  16. data/lib/r18n-core/untranslated.rb +35 -33
  17. data/lib/r18n-core/utils.rb +26 -25
  18. data/lib/r18n-core/version.rb +4 -1
  19. data/lib/r18n-core/yaml_loader.rb +26 -25
  20. data/lib/r18n-core/yaml_methods.rb +25 -28
  21. data/locales/af.rb +15 -8
  22. data/locales/az.rb +19 -12
  23. data/locales/bg.rb +16 -9
  24. data/locales/ca.rb +16 -9
  25. data/locales/cs.rb +27 -20
  26. data/locales/da.rb +15 -8
  27. data/locales/de.rb +16 -9
  28. data/locales/en-au.rb +10 -5
  29. data/locales/en-gb.rb +12 -5
  30. data/locales/en-us.rb +12 -5
  31. data/locales/en.rb +29 -22
  32. data/locales/eo.rb +14 -7
  33. data/locales/es-us.rb +12 -5
  34. data/locales/es.rb +14 -7
  35. data/locales/fa.rb +48 -32
  36. data/locales/fi.rb +19 -12
  37. data/locales/fr.rb +22 -15
  38. data/locales/gl.rb +15 -8
  39. data/locales/hr.rb +24 -17
  40. data/locales/hu.rb +28 -21
  41. data/locales/id.rb +14 -7
  42. data/locales/it.rb +21 -14
  43. data/locales/ja.rb +15 -8
  44. data/locales/kk.rb +17 -10
  45. data/locales/ko.rb +15 -9
  46. data/locales/lv.rb +24 -17
  47. data/locales/mn.rb +10 -3
  48. data/locales/nb.rb +15 -8
  49. data/locales/nl.rb +15 -8
  50. data/locales/no.rb +11 -16
  51. data/locales/pl.rb +26 -19
  52. data/locales/pt-br.rb +12 -5
  53. data/locales/pt.rb +17 -10
  54. data/locales/ru.rb +26 -19
  55. data/locales/sk.rb +27 -20
  56. data/locales/sr-latn.rb +27 -22
  57. data/locales/sv-se.rb +15 -8
  58. data/locales/th.rb +27 -20
  59. data/locales/tr.rb +16 -9
  60. data/locales/uk.rb +19 -12
  61. data/locales/vi.rb +14 -7
  62. data/locales/zh-cn.rb +12 -5
  63. data/locales/zh-tw.rb +15 -8
  64. data/locales/zh.rb +14 -7
  65. data/r18n-core.gemspec +5 -3
  66. data/spec/filters_spec.rb +71 -67
  67. data/spec/i18n_spec.rb +73 -51
  68. data/spec/locale_spec.rb +73 -68
  69. data/spec/locales/cs_spec.rb +2 -2
  70. data/spec/locales/en-us_spec.rb +9 -9
  71. data/spec/locales/en_spec.rb +2 -2
  72. data/spec/locales/fa_spec.rb +3 -3
  73. data/spec/locales/fr_spec.rb +2 -2
  74. data/spec/locales/hu_spec.rb +7 -7
  75. data/spec/locales/it_spec.rb +3 -3
  76. data/spec/locales/no_spec.rb +9 -0
  77. data/spec/locales/pl_spec.rb +2 -2
  78. data/spec/locales/ru_spec.rb +2 -2
  79. data/spec/locales/sk_spec.rb +2 -2
  80. data/spec/locales/th_spec.rb +2 -2
  81. data/spec/locales/vi_spec.rb +2 -2
  82. data/spec/r18n_spec.rb +44 -38
  83. data/spec/spec_helper.rb +13 -9
  84. data/spec/translated_spec.rb +48 -31
  85. data/spec/translation_spec.rb +29 -27
  86. data/spec/translations/general/en.yml +0 -2
  87. data/spec/yaml_loader_spec.rb +22 -18
  88. metadata +5 -3
@@ -1,21 +1,21 @@
1
- =begin
2
- Mixin with common methods.
1
+ # frozen_string_literal: true
3
2
 
4
- Copyright (C) 2010 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
5
-
6
- This program is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU Lesser General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- This program is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU Lesser General Public License for more details.
15
-
16
- You should have received a copy of the GNU Lesser General Public License
17
- along with this program. If not, see <http://www.gnu.org/licenses/>.
18
- =end
3
+ # Mixin with common methods.
4
+ #
5
+ # Copyright (C) 2010 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  module R18n
21
21
  # Useful aliases. Set I18n object before use them:
@@ -1,24 +1,23 @@
1
- =begin
2
- I18n support.
1
+ # frozen_string_literal: true
3
2
 
4
- Copyright (C) 2008 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
5
-
6
- This program is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU Lesser General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- This program is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU Lesser General Public License for more details.
15
-
16
- You should have received a copy of the GNU Lesser General Public License
17
- along with this program. If not, see <http://www.gnu.org/licenses/>.
18
- =end
3
+ # I18n support.
4
+ #
5
+ # Copyright (C) 2008 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  require 'date'
21
- require 'pathname'
22
21
 
23
22
  module R18n
24
23
  # General class to i18n support in your application. It load Translation and
@@ -103,7 +102,7 @@ module R18n
103
102
  locales = str.split(',')
104
103
  locales.map! do |locale|
105
104
  locale = locale.split ';q='
106
- if 1 == locale.size
105
+ if locale.size == 1
107
106
  [locale[0], 1.0]
108
107
  else
109
108
  [locale[0], locale[1].to_f]
@@ -117,7 +116,7 @@ module R18n
117
116
  # argument.
118
117
  def self.convert_places(places)
119
118
  Array(places).map! do |loader|
120
- if loader.respond_to? :available and loader.respond_to? :load
119
+ if loader.respond_to?(:available) && loader.respond_to?(:load)
121
120
  loader
122
121
  else
123
122
  R18n.default_loader.new(loader)
@@ -144,7 +143,7 @@ module R18n
144
143
  def initialize(locales, translation_places = nil, opts = {})
145
144
  locales = Array(locales)
146
145
 
147
- if not locales.empty? and Locale.exists? locales.first
146
+ if !locales.empty? && Locale.exists?(locales.first)
148
147
  locales += Locale.load(locales.first).sublocales
149
148
  end
150
149
  locales << @@default
@@ -166,14 +165,15 @@ module R18n
166
165
 
167
166
  @translation_places = self.class.convert_places(@original_places)
168
167
 
169
- if opts[:on_filters] or opts[:off_filters]
170
- @filters = CustomFilterList.new(opts[:on_filters], opts[:off_filters])
171
- else
172
- @filters = GlobalFilterList.instance
173
- end
168
+ @filters =
169
+ if opts[:on_filters] || opts[:off_filters]
170
+ CustomFilterList.new(opts[:on_filters], opts[:off_filters])
171
+ else
172
+ GlobalFilterList.instance
173
+ end
174
174
 
175
175
  key = translation_cache_key
176
- if R18n.cache.has_key? key
176
+ if R18n.cache.key? key
177
177
  @locale, @translation = *R18n.cache[key]
178
178
  else
179
179
  reload!
@@ -187,8 +187,9 @@ module R18n
187
187
 
188
188
  # Return unique key for current locales in translation and places.
189
189
  def translation_cache_key
190
- @available_codes ||= @translation_places.inject([]) { |all, i|
191
- all + i.available }.uniq.map { |i| i.code.downcase }
190
+ @available_codes ||= @translation_places
191
+ .inject([]) { |all, i| all + i.available }
192
+ .uniq.map { |i| i.code.downcase }
192
193
  (@locales_codes & @available_codes).join(',') + '@' +
193
194
  @filters.hash.to_s + '_' +
194
195
  R18n.default_loader.hash.to_s + '_' +
@@ -202,18 +203,22 @@ module R18n
202
203
  @translation_places = self.class.convert_places(@original_places)
203
204
 
204
205
  available_in_places = @translation_places.map { |i| [i, i.available] }
205
- available_in_extensions = R18n.extension_places.map {|i| [i, i.available]}
206
+ available_in_extensions =
207
+ R18n.extension_places.map { |i| [i, i.available] }
206
208
 
207
- unless @locale
208
- available_in_places.each do |place, available|
209
+ unless defined? @locale
210
+ # It's array!
211
+ # rubocop:disable Perfomance/HashEachMethods
212
+ available_in_places.each do |_place, available|
209
213
  @locales.each do |locale|
210
214
  if available.include? locale
211
215
  @locale = locale
212
216
  break
213
217
  end
214
218
  end
215
- break if @locale
219
+ break if defined? @locale
216
220
  end
221
+ # rubocop:enable Perfomance/HashEachMethods
217
222
  end
218
223
  @locale ||= @locales.first
219
224
  unless @locale.supported?
@@ -228,17 +233,19 @@ module R18n
228
233
  @translation = Translation.new(@locale, '', filters: @filters)
229
234
  @locales.each do |locale|
230
235
  loaded = false
236
+
231
237
  available_in_places.each do |place, available|
232
238
  if available.include? locale
233
239
  @translation.merge! place.load(locale), locale
234
240
  loaded = true
235
241
  end
236
242
  end
237
- if loaded
238
- available_in_extensions.each do |extension, available|
239
- if available.include? locale
240
- @translation.merge! extension.load(locale), locale
241
- end
243
+
244
+ next unless loaded
245
+
246
+ available_in_extensions.each do |extension, available|
247
+ if available.include? locale
248
+ @translation.merge! extension.load(locale), locale
242
249
  end
243
250
  end
244
251
  end
@@ -267,7 +274,7 @@ module R18n
267
274
  def localize(object, format = nil, *params)
268
275
  locale.localize(object, format, self, *params)
269
276
  end
270
- alias :l :localize
277
+ alias l localize
271
278
 
272
279
  # Return translations.
273
280
  def t
@@ -1,23 +1,22 @@
1
- =begin
2
- Locale to i18n support.
1
+ # frozen_string_literal: true
2
+
3
+ # Locale to i18n support.
4
+ #
5
+ # Copyright (C) 2008 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
3
19
 
4
- Copyright (C) 2008 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
5
-
6
- This program is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU Lesser General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- This program is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU Lesser General Public License for more details.
15
-
16
- You should have received a copy of the GNU Lesser General Public License
17
- along with this program. If not, see <http://www.gnu.org/licenses/>.
18
- =end
19
-
20
- require 'pathname'
21
20
  require 'singleton'
22
21
  require 'bigdecimal'
23
22
 
@@ -55,7 +54,7 @@ module R18n
55
54
  # You can see more available data about locale in samples in
56
55
  # <tt>locales/</tt> dir.
57
56
  class Locale
58
- LOCALES_DIR = Pathname(__FILE__).dirname.expand_path + '../../locales/'
57
+ LOCALES_DIR = File.join(__dir__, '..', '..', 'locales')
59
58
 
60
59
  @@loaded = {}
61
60
 
@@ -68,19 +67,19 @@ module R18n
68
67
 
69
68
  # Is +locale+ has info file.
70
69
  def self.exists?(locale)
71
- File.exists?(File.join(LOCALES_DIR, locale.to_s + '.rb'))
70
+ File.exist?(File.join(LOCALES_DIR, "#{locale}.rb"))
72
71
  end
73
72
 
74
73
  # Load locale by RFC 3066 +code+.
75
74
  def self.load(code)
76
75
  original = code.to_s.gsub(/[^-_a-zA-Z]/, '')
77
- code = original.gsub('_', '-').downcase
76
+ code = original.tr('_', '-').downcase
78
77
 
79
78
  @@loaded[code] ||= begin
80
79
  if exists? code
81
- require LOCALES_DIR.join("#{code}.rb").to_s
82
- name = code.gsub(/[\w\d]+/) { |i| i.capitalize }.gsub('-', '')
83
- eval('R18n::Locales::' + name).new
80
+ require File.join(LOCALES_DIR, "#{code}.rb")
81
+ name = code.gsub(/\w+/, &:capitalize).delete('-')
82
+ R18n::Locales.const_get(name).new
84
83
  else
85
84
  UnsupportedLocale.new(original)
86
85
  end
@@ -111,7 +110,7 @@ module R18n
111
110
  lang.downcase + (culture ? '-' + culture.upcase : '')
112
111
  end
113
112
 
114
- set sublocales: %w{en},
113
+ set sublocales: %w[en],
115
114
  week_start: :monday,
116
115
  time_am: 'AM',
117
116
  time_pm: 'PM',
@@ -119,16 +118,26 @@ module R18n
119
118
  full_format: '%e %B',
120
119
  year_format: '_ %Y'
121
120
 
122
- def month_standalone; month_names; end
123
- def month_abbrs; month_names; end
124
- def wday_abbrs; wday_names; end
121
+ def month_standalone
122
+ month_names
123
+ end
124
+
125
+ def month_abbrs
126
+ month_names
127
+ end
128
+
129
+ def wday_abbrs
130
+ wday_names
131
+ end
125
132
 
126
133
  # Is locale has left-to-right write direction.
127
- def ltr?; true; end
134
+ def ltr?
135
+ true
136
+ end
128
137
 
129
138
  # Is another locale has same code.
130
- def ==(locale)
131
- self.class == locale.class
139
+ def ==(other)
140
+ self.class == other.class
132
141
  end
133
142
 
134
143
  # Is locale has information file. In this class always return true.
@@ -156,13 +165,13 @@ module R18n
156
165
  format_float(obj.to_f)
157
166
  when Time, DateTime, Date
158
167
  return strftime(obj, format) if format.is_a? String
159
- return month_standalone[obj.month - 1] if :month == format
160
- return obj.to_s if :human == format and not params.first.is_a? I18n
168
+ return month_standalone[obj.month - 1] if format == :month
169
+ return obj.to_s if format == :human && !params.first.is_a?(I18n)
161
170
 
162
171
  type = obj.is_a?(Date) && !obj.is_a?(DateTime) ? 'date' : 'time'
163
- format = :standard unless format
172
+ format ||= :standard
164
173
 
165
- unless [:human, :full, :standard].include? format
174
+ unless %i[human full standard].include? format
166
175
  raise ArgumentError, "Unknown time formatter #{format}"
167
176
  end
168
177
 
@@ -176,7 +185,7 @@ module R18n
176
185
  # It will also put real typographic minus.
177
186
  def format_integer(integer)
178
187
  str = integer.to_s
179
- str[0] = '−' if 0 > integer # Real typographic minus
188
+ str[0] = '−' if integer < 0 # Real typographic minus
180
189
  group = number_group
181
190
 
182
191
  str.gsub(/(\d)(?=(\d\d\d)+(?!\d))/) do |match|
@@ -188,7 +197,7 @@ module R18n
188
197
  # It will also put real typographic minus.
189
198
  def format_float(float)
190
199
  decimal = number_decimal
191
- self.format_integer(float.to_i) + decimal + float.to_s.split('.').last
200
+ format_integer(float.to_i) + decimal + float.to_s.split('.').last
192
201
  end
193
202
 
194
203
  # Same that <tt>Time.strftime</tt>, but translate months and week days
@@ -197,20 +206,21 @@ module R18n
197
206
  def strftime(time, format)
198
207
  translated = ''
199
208
  format.scan(/%[EO]?.|./o) do |c|
200
- case c.sub(/^%[EO]?(.)$/o, '%\\1')
201
- when '%A'
202
- translated << wday_names[time.wday]
203
- when '%a'
204
- translated << wday_abbrs[time.wday]
205
- when '%B'
206
- translated << month_names[time.month - 1]
207
- when '%b'
208
- translated << month_abbrs[time.month - 1]
209
- when '%p'
210
- translated << (time.hour < 12 ? time_am : time_pm)
211
- else
212
- translated << c
213
- end
209
+ translated +=
210
+ case c.sub(/^%[EO]?(.)$/o, '%\\1')
211
+ when '%A'
212
+ wday_names[time.wday]
213
+ when '%a'
214
+ wday_abbrs[time.wday]
215
+ when '%B'
216
+ month_names[time.month - 1]
217
+ when '%b'
218
+ month_abbrs[time.month - 1]
219
+ when '%p'
220
+ time.hour < 12 ? time_am : time_pm
221
+ else
222
+ c
223
+ end
214
224
  end
215
225
  time.strftime(translated)
216
226
  end
@@ -223,42 +233,40 @@ module R18n
223
233
  # Format +time+ in human usable form. For example “5 minutes ago” or
224
234
  # “yesterday”. In +now+ you can set base time, which be used to get relative
225
235
  # time. For special cases you can replace it in locale’s class.
226
- def format_time_human(time, i18n, now = Time.now, *params)
236
+ def format_time_human(time, i18n, now = Time.now, *_params)
227
237
  diff = time - now
228
238
  minutes = time.is_a?(DateTime) ? diff * 24 * 60.0 : diff / 60.0
229
239
  diff = minutes.abs
230
- if (diff > 24 * 60) or (time.mday != now.mday and diff > 12 * 24)
240
+ if (diff > 24 * 60) || (time.mday != now.mday && diff > 12 * 24)
231
241
  format_time(format_date_human(time.to_date, i18n, now.to_date), time)
242
+ elsif minutes > -1 && minutes < 1
243
+ i18n.human_time.now
244
+ elsif minutes >= 60
245
+ i18n.human_time.after_hours((diff / 60.0).floor)
246
+ elsif minutes <= -60
247
+ i18n.human_time.hours_ago((diff / 60.0).floor)
248
+ elsif minutes > 0
249
+ i18n.human_time.after_minutes(minutes.round)
232
250
  else
233
- if -1 < minutes and 1 > minutes
234
- i18n.human_time.now
235
- elsif 60 <= minutes
236
- i18n.human_time.after_hours((diff / 60.0).floor)
237
- elsif -60 >= minutes
238
- i18n.human_time.hours_ago((diff / 60.0).floor)
239
- elsif 0 < minutes
240
- i18n.human_time.after_minutes(minutes.round)
241
- else
242
- i18n.human_time.minutes_ago(minutes.round.abs)
243
- end
251
+ i18n.human_time.minutes_ago(minutes.round.abs)
244
252
  end
245
253
  end
246
254
 
247
255
  # Format +time+ in compact form. For example, “12/31/09 12:59”.
248
- def format_time_standard(time, *params)
256
+ def format_time_standard(time, *_params)
249
257
  format_time(format_date_standard(time), time)
250
258
  end
251
259
 
252
260
  # Format +time+ in most official form. For example, “December 31st, 2009
253
261
  # 12:59”. For special cases you can replace it in locale’s class.
254
- def format_time_full(time, *params)
262
+ def format_time_full(time, *_params)
255
263
  format_time(format_date_full(time), time)
256
264
  end
257
265
 
258
266
  # Format +date+ in human usable form. For example “5 days ago” or
259
267
  # “yesterday”. In +now+ you can set base time, which be used to get relative
260
268
  # time. For special cases you can replace it in locale’s class.
261
- def format_date_human(date, i18n, now = Date.today, *params)
269
+ def format_date_human(date, i18n, now = Date.today, *_params)
262
270
  days = (date - now).to_i
263
271
  case days
264
272
  when -6..-2
@@ -277,14 +285,14 @@ module R18n
277
285
  end
278
286
 
279
287
  # Format +date+ in compact form. For example, “12/31/09”.
280
- def format_date_standard(date, *params)
288
+ def format_date_standard(date, *_params)
281
289
  strftime(date, date_format)
282
290
  end
283
291
 
284
292
  # Format +date+ in most official form. For example, “December 31st, 2009”.
285
293
  # For special cases you can replace it in locale’s class. If +year+ is false
286
294
  # date will be without year.
287
- def format_date_full(date, year = true, *params)
295
+ def format_date_full(date, year = true, *_params)
288
296
  format = full_format
289
297
  format = year_format.sub('_', format) if year
290
298
  strftime(date, format)
@@ -304,5 +312,6 @@ module R18n
304
312
  end
305
313
  end
306
314
 
315
+ # Namespace for Locale sub-classes
307
316
  module Locales; end
308
317
  end