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.



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

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.



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

def code
  @code
end

#downcased_codeObject (readonly)

Returns the value of attribute downcased_code.



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

def downcased_code
  @downcased_code
end

#languageObject (readonly)

Returns the value of attribute language.



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

def language
  @language
end

#parentObject (readonly)

Returns the value of attribute parent.



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

def parent
  @parent
end

#regionObject (readonly)

Returns the value of attribute region.



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

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
115
# File 'lib/r18n-core/locale.rb', line 110

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

Instance Method Details

#==(other) ⇒ Object

Is another locale has same code.



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

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

#format_date_full(date, year: true, **_kwargs) ⇒ 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.



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

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

#format_date_human(date, *_args, i18n:, now: Date.today, **_kwargs) ⇒ 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.



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

def format_date_human(date, *_args, i18n:, now: Date.today, **_kwargs)
  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, year: date.year != now.year)
  end
end

#format_date_standard(date, *_params) ⇒ Object

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



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

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.



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

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.



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

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, **_kwargs) ⇒ Object

Format ‘time` and set `date`



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

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

#format_time_full(time, **kwargs) ⇒ 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
# File 'lib/r18n-core/locale.rb', line 289

def format_time_full(time, **kwargs)
  format_time(format_date_full(time, **kwargs), time, **kwargs)
end

#format_time_human(time, i18n:, now: time.class.now, **_kwargs) ⇒ 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.



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

def format_time_human(time, i18n:, now: time.class.now, **_kwargs)
  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, now: now.to_date, i18n: i18n), 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, *args, **kwargs) ⇒ Object

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



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

def format_time_standard(time, *args, **kwargs)
  format_time(format_date_standard(time), time, *args, **kwargs)
end

#inspectObject

Human readable locale code and title.



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

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

#localize(obj, format = nil, *args, **kwargs) ⇒ 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`.



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
207
# File 'lib/r18n-core/locale.rb', line 179

def localize(obj, format = nil, *args, **kwargs)
  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 && !kwargs.key?(: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, *args, **kwargs
  else
    format_method_name =
      "format_#{Utils.underscore(obj.class.name).tr('/', '_')}_#{format}"

    return obj.to_s unless respond_to? format_method_name

    send format_method_name, obj, *args, **kwargs
  end
end

#ltr?Boolean

Is locale has left-to-right write direction.

Returns:

  • (Boolean)


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

def ltr?
  true
end

#month_abbrsObject



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

def month_abbrs
  month_names
end

#month_standaloneObject



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

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.



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

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.



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

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)


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

def supported?
  true
end

#wday_abbrsObject



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

def wday_abbrs
  wday_names
end