Class: R18n::Locale

Inherits:
Object
  • Object
show all
Defined in:
lib/r18n-core/locale.rb

Overview

Information about locale (language, country and other special variant preferences). Locale was named by RFC 3066. For example, locale for French speaking people in Canada will be ‘fr-CA`.

Locale classes are placed in ‘R18n::Locales` module and storage install `locales/` dir.

Each locale has ‘sublocales` – often known languages for people from this locale. For example, many Belorussians know Russian and English. If there is’t translation for Belorussian, it will be searched in Russian and next in English translations.

Usage

Get Russian locale and print it information

ru = R18n.locale('ru')
ru.title #=> "Русский"
ru.code  #=> "ru"
ru.ltr?  #=> true

Available data

  • ‘code` – locale RFC 3066 code;

  • ‘title` – locale name on it language;

  • ‘ltr?` – true on left-to-right writing direction, false for Arabic and Hebrew);

  • ‘sublocales` – often known languages for people from this locale;

  • ‘week_start` – does week start from `:monday` or `:sunday`.

You can see more available data about locale in samples in ‘locales/` dir.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLocale

Returns a new instance of Locale.



119
120
121
122
123
124
125
126
127
128
# File 'lib/r18n-core/locale.rb', line 119

def initialize
  language, region =
    self.class.name.split('::').last.split(/([A-Z][a-z]+)/)[1, 2]
  @language = language.downcase.freeze
  @region = region.upcase.freeze if region
  @code = "#{@language}#{"-#{region}" if region}"
  @downcased_code = @code.downcase.tr('-', '_').freeze

  @parent = self.class.superclass.new
end

Instance Attribute Details

#codeObject (readonly)

Returns the value of attribute code.



117
118
119
# File 'lib/r18n-core/locale.rb', line 117

def code
  @code
end

#downcased_codeObject (readonly)

Returns the value of attribute downcased_code.



117
118
119
# File 'lib/r18n-core/locale.rb', line 117

def downcased_code
  @downcased_code
end

#languageObject (readonly)

Returns the value of attribute language.



117
118
119
# File 'lib/r18n-core/locale.rb', line 117

def language
  @language
end

#parentObject (readonly)

Returns the value of attribute parent.



117
118
119
# File 'lib/r18n-core/locale.rb', line 117

def parent
  @parent
end

#regionObject (readonly)

Returns the value of attribute region.



117
118
119
# File 'lib/r18n-core/locale.rb', line 117

def region
  @region
end

Class Method Details

.capitalize(code) ⇒ Object



73
74
75
76
77
78
79
80
81
82
# File 'lib/r18n-core/locale.rb', line 73

def capitalize(code)
  lang, region = code.gsub(/\..+/, '').split('-')
  return unless lang

  lang.capitalize!
  return lang unless region

  region.size > 2 ? region.capitalize! : region.upcase!
  "#{lang}#{region}"
end

.exists?(locale) ⇒ Boolean

Is ‘locale` constant defined?

Returns:

  • (Boolean)


61
62
63
64
65
66
67
# File 'lib/r18n-core/locale.rb', line 61

def exists?(locale)
  locale = sanitize_code locale
  name = capitalize(locale)
  return false unless name

  R18n::Locales.const_defined?(name)
end

.load(code) ⇒ Object

Load locale by RFC 3066 ‘code`.



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/r18n-core/locale.rb', line 85

def load(code)
  code = sanitize_code code
  name = capitalize(code)
  return unless name

  @loaded[code] ||= begin
    if exists?(code)
      R18n::Locales.const_get(name).new
    else
      UnsupportedLocale.new(code)
    end
  end
end

.sanitize_code(code) ⇒ Object



69
70
71
# File 'lib/r18n-core/locale.rb', line 69

def sanitize_code(code)
  code.to_s.gsub(/[^-_a-zA-Z]/, '').tr('_', '-').downcase
end

.set(properties) ⇒ Object

Set locale ‘properties`. Locale class will have methods for each property name, which return property value:

class R18n::Locales::En < R18n::Locale
  set title: 'English',
      code:  'en'
end

locale = R18n::Locales::En.new
locale.title #=> "English"
locale.code  #=> "en"


110
111
112
113
114
# File 'lib/r18n-core/locale.rb', line 110

def set(properties)
  properties.each_pair do |key, value|
    define_method(key) { value }
  end
end

Instance Method Details

#==(other) ⇒ Object

Is another locale has same code.



157
158
159
# File 'lib/r18n-core/locale.rb', line 157

def ==(other)
  self.class == other.class
end

#format_date_full(date, year = true, *_params) ⇒ Object

Format ‘date` in most official form. For example, “December 31st, 2009”. For special cases you can replace it in locale’s class. If ‘year` is false date will be without year.



323
324
325
326
327
# File 'lib/r18n-core/locale.rb', line 323

def format_date_full(date, year = true, *_params)
  format = full_format
  format = year_format.sub('_', format) if year
  strftime(date, format)
end

#format_date_human(date, i18n, now = Date.today, *_params) ⇒ Object

Format ‘date` in human usable form. For example “5 days ago” or “yesterday”. In `now` you can set base time, which be used to get relative time. For special cases you can replace it in locale’s class.



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/r18n-core/locale.rb', line 297

def format_date_human(date, i18n, now = Date.today, *_params)
  days = (date - now).to_i
  case days
  when -6..-2
    i18n.human_time.days_ago(days.abs)
  when -1
    i18n.human_time.yesterday
  when 0
    i18n.human_time.today
  when 1
    i18n.human_time.tomorrow
  when 2..6
    i18n.human_time.after_days(days)
  else
    format_date_full(date, date.year != now.year)
  end
end

#format_date_standard(date, *_params) ⇒ Object

Format ‘date` in compact form. For example, “12/31/09”.



316
317
318
# File 'lib/r18n-core/locale.rb', line 316

def format_date_standard(date, *_params)
  strftime(date, date_format)
end

#format_float(float) ⇒ Object

Returns the float in ‘String` form, according to the rules of the locale. It will also put real typographic minus.



222
223
224
225
# File 'lib/r18n-core/locale.rb', line 222

def format_float(float)
  decimal = number_decimal
  format_integer(float.to_i) + decimal + float.to_s.split('.').last
end

#format_integer(integer) ⇒ Object

Returns the integer in ‘String` form, according to the rules of the locale. It will also put real typographic minus.



210
211
212
213
214
215
216
217
218
# File 'lib/r18n-core/locale.rb', line 210

def format_integer(integer)
  str = integer.to_s
  str[0] = '' if integer.negative? # Real typographic minus
  group = number_group

  str.gsub(/(\d)(?=(\d\d\d)+(?!\d))/) do |match|
    match + group
  end
end

#format_time(date, time, with_seconds: false) ⇒ Object

Format ‘time` and set `date`



253
254
255
256
257
# File 'lib/r18n-core/locale.rb', line 253

def format_time(date, time, with_seconds: false)
  strftime(
    time, with_seconds ? time_with_seconds_format : time_format
  ).sub('_', date.to_s)
end

#format_time_full(time, *params) ⇒ Object

Format ‘time` in most official form. For example, “December 31st, 2009 12:59”. For special cases you can replace it in locale’s class.



289
290
291
292
# File 'lib/r18n-core/locale.rb', line 289

def format_time_full(time, *params)
  options = params.last.is_a?(Hash) ? params.last : {}
  format_time(format_date_full(time), time, **options)
end

#format_time_human(time, i18n, now = time.class.now, *_params) ⇒ Object

Format ‘time` in human usable form. For example “5 minutes ago” or “yesterday”. In `now` you can set base time, which be used to get relative time. For special cases you can replace it in locale’s class.



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/r18n-core/locale.rb', line 262

def format_time_human(time, i18n, now = time.class.now, *_params)
  diff = time - now
  minutes = time.is_a?(DateTime) ? diff * 24 * 60.0 : diff / 60.0
  diff = minutes.abs
  if (diff > 24 * 60) || (time.mday != now.mday && diff > 12 * 24)
    format_time(format_date_human(time.to_date, i18n, now.to_date), time)
  elsif minutes > -1 && minutes < 1
    i18n.human_time.now
  elsif minutes >= 60
    i18n.human_time.after_hours((diff / 60.0).floor)
  elsif minutes <= -60
    i18n.human_time.hours_ago((diff / 60.0).floor)
  elsif minutes.positive?
    i18n.human_time.after_minutes(minutes.round)
  else
    i18n.human_time.minutes_ago(minutes.round.abs)
  end
end

#format_time_standard(time, *params) ⇒ Object

Format ‘time` in compact form. For example, “12/31/09 12:59”.



282
283
284
285
# File 'lib/r18n-core/locale.rb', line 282

def format_time_standard(time, *params)
  options = params.last.is_a?(Hash) ? params.last : {}
  format_time(format_date_standard(time), time, **options)
end

#inspectObject

Human readable locale code and title.



167
168
169
# File 'lib/r18n-core/locale.rb', line 167

def inspect
  "Locale #{code} (#{title})"
end

#localize(obj, format = nil, *params) ⇒ Object

Convert ‘object` to `String`. It support `Integer`, `Float`, `Time`, `Date` and `DateTime`.

For time classes you can set ‘format` in standard `strftime` form, `:full` (“01 Jule, 2009”), `:human` (“yesterday”), `:standard` (“07/01/09”) or `:month` for standalone month name. Default format is `:standard`.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/r18n-core/locale.rb', line 178

def localize(obj, format = nil, *params)
  case obj
  when Integer
    format_integer(obj)
  when Float, BigDecimal
    format_float(obj.to_f)
  when Time, DateTime, Date
    return strftime(obj, format) if format.is_a? String
    return month_standalone[obj.month - 1] if format == :month
    return obj.to_s if format == :human && !params.first.is_a?(I18n)

    type = obj.is_a?(Date) && !obj.is_a?(DateTime) ? 'date' : 'time'
    format ||= :standard
    format_method_name = "format_#{type}_#{format}"

    unless respond_to? format_method_name
      raise ArgumentError, "Unknown time formatter #{format}"
    end

    send format_method_name, obj, *params
  else
    format_method_name =
      "format_#{Utils.underscore(obj.class.name)}_#{format}"

    return obj.to_s unless respond_to? format_method_name

    send format_method_name, obj, *params
  end
end

#ltr?Boolean

Is locale has left-to-right write direction.

Returns:

  • (Boolean)


152
153
154
# File 'lib/r18n-core/locale.rb', line 152

def ltr?
  true
end

#month_abbrsObject



143
144
145
# File 'lib/r18n-core/locale.rb', line 143

def month_abbrs
  month_names
end

#month_standaloneObject



139
140
141
# File 'lib/r18n-core/locale.rb', line 139

def month_standalone
  month_names
end

#pluralize(number) ⇒ Object

Return pluralization type for ‘number` of items. This is simple form. For special cases you can replace it in locale’s class.



331
332
333
334
335
336
337
338
339
340
# File 'lib/r18n-core/locale.rb', line 331

def pluralize(number)
  case number
  when 0
    0
  when 1
    1
  else
    'n'
  end
end

#strftime(time, format) ⇒ Object

Same that ‘Time.strftime`, but translate months and week days names. In `time` you can use `Time`, `DateTime` or `Date` object. In `format` you can use standard `strftime` format.



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/r18n-core/locale.rb', line 230

def strftime(time, format)
  translated = ''
  format.scan(/%[EO]?.|./o) do |c|
    translated +=
      case c.sub(/^%[EO]?(.)$/o, '%\\1')
      when '%A'
        wday_names[time.wday]
      when '%a'
        wday_abbrs[time.wday]
      when '%B'
        month_names[time.month - 1]
      when '%b'
        month_abbrs[time.month - 1]
      when '%p'
        time.hour < 12 ? time_am : time_pm
      else
        c
      end
  end
  time.strftime(translated)
end

#supported?Boolean

Is locale has information file. In this class always return true.

Returns:

  • (Boolean)


162
163
164
# File 'lib/r18n-core/locale.rb', line 162

def supported?
  true
end

#wday_abbrsObject



147
148
149
# File 'lib/r18n-core/locale.rb', line 147

def wday_abbrs
  wday_names
end