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

#initialize ⇒ Locale

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

#code ⇒ Object (readonly)

Returns the value of attribute code.



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

def code
  @code
end

#downcased_code ⇒ Object (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

#language ⇒ Object (readonly)

Returns the value of attribute language.



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

def language
  @language
end

#parent ⇒ Object (readonly)

Returns the value of attribute parent.



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

def parent
  @parent
end

#region ⇒ Object (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
# File 'lib/r18n-core/locale.rb', line 85

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

  @loaded[code] ||=
    if exists?(code)
      R18n::Locales.const_get(name).new
    else
      UnsupportedLocale.new(code)
    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"


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

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.



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

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.



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

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.



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, *_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".



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.



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

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.



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

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



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

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



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

def format_time_full(time, **)
  format_time(format_date_full(time, **), time, **)
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.



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

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

Format time in compact form. For example, "12/31/09 12:59".



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

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

#inspect ⇒ Object

Human readable locale code and title.



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

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

#localize(obj, format = nil, **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.



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

def localize(obj, format = nil, *, **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, *, **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, *, **kwargs
  end
end

#ltr? ⇒ Boolean

Is locale has left-to-right write direction.

Returns:

  • (Boolean)


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

def ltr?
  true
end

#month_abbrs ⇒ Object



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

def month_abbrs
  month_names
end

#month_standalone ⇒ Object



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

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.



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

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)


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

def supported?
  true
end

#wday_abbrs ⇒ Object



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

def wday_abbrs
  wday_names
end