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 files is placed in locales/ dir in YAML files.

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.load('ru')
ru.title #=> "Русский"
ru.code  #=> "ru"
ru.ltr?  #=> true

Available data

  • code: locale RFC 3066 code;

  • title: locale name on it language;

  • direction: writing direction, ltr or rtl (for Arabic and Hebrew);

  • sublocales: often known languages for people from this locale;

  • include: locale code to include it data, optional.

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

Extend locale

If language need some special logic (for example, another pluralization or time formatters) you can just change Locale class. Create R18n::Locales::Code class in base/code.rb, extend R18n::Locale and rewrite methods (for example, pluralization or format_date_full).

Constant Summary collapse

LOCALES_DIR =
Pathname(__FILE__).dirname.expand_path + '../../locales/'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Locale

Create locale object with locale data.

This is internal a constructor. To load translation use R18n::Translation.load(locales, translations_dir).



124
125
126
# File 'lib/r18n-core/locale.rb', line 124

def initialize(data)
  @data = data
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



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

def data
  @data
end

Class Method Details

.availableObject

All available locales



65
66
67
68
69
# File 'lib/r18n-core/locale.rb', line 65

def self.available
  Dir.glob(File.join(LOCALES_DIR, '*.yml')).map do |i|
    File.basename(i, '.yml')
  end
end

.exists?(locale) ⇒ Boolean

Is locale has info file

Returns:

  • (Boolean)


72
73
74
# File 'lib/r18n-core/locale.rb', line 72

def self.exists?(locale)
  File.exists?(File.join(LOCALES_DIR, locale + '.yml'))
end

.load(code) ⇒ Object

Load locale by RFC 3066 code



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/r18n-core/locale.rb', line 77

def self.load(code)
  code = code.to_s
  code.delete! '/'
  code.delete! '\\'
  code.delete! ';'
  original = code
  code = code.downcase
  
  return UnsupportedLocale.new(original) unless exists? code
  
  data = {}
  klass = R18n::Locale
  default_loaded = false
  
  while code and exists? code
    file = LOCALES_DIR + "#{code}.yml"
    default_loaded = true if I18n.default == code
    
    if R18n::Locale == klass and File.exists? LOCALES_DIR + "#{code}.rb"
      require LOCALES_DIR + "#{code}.rb"
      name = code.gsub(/[\w\d]+/) { |i| i.capitalize }.gsub('-', '')
      klass = eval 'R18n::Locales::' + name
    end
    
    loaded = YAML.load_file(file)
    code = loaded['include']
    data = Utils.deep_merge! loaded, data
  end
  
  unless default_loaded
    code = I18n.default
    while code and exists? code
      loaded = YAML.load_file(LOCALES_DIR + "#{code}.yml")
      code = loaded['include']
      data = Utils.deep_merge! loaded, data
    end
  end
  
  klass.new(data)
end

Instance Method Details

#==(locale) ⇒ Object

Is another locale has same code



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

def ==(locale)
  code.downcase == locale.code.downcase
end

#[](name) ⇒ Object

Get information about locale



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

def [](name)
  @data[name]
end

#codeObject

Locale RFC 3066 code.



129
130
131
# File 'lib/r18n-core/locale.rb', line 129

def code
  @data['code']
end

#format_date_full(i18n, date, year = true) ⇒ 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.



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

def format_date_full(i18n, date, year = true)
  format = @data['time']['full']
  format = @data['time']['year'].sub('_', format) if year
  strftime(date, format)
end

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



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/r18n-core/locale.rb', line 256

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

#format_date_standard(i18n, date) ⇒ Object

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



275
276
277
# File 'lib/r18n-core/locale.rb', line 275

def format_date_standard(i18n, date)
  strftime(date, @data['time']['date'])
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.



177
178
179
180
# File 'lib/r18n-core/locale.rb', line 177

def format_float(float)
  decimal = @data['numbers']['decimal_separator']
  self.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.



165
166
167
168
169
170
171
172
173
# File 'lib/r18n-core/locale.rb', line 165

def format_integer(integer)
  str = integer.to_s
  str[0] = '' if 0 > integer # Real typographic minus
  group = @data['numbers']['group_delimiter']
  
  str.gsub(/(\d)(?=(\d\d\d)+(?!\d))/) do |match|
    match + group
  end
end

#format_time(time) ⇒ Object

Format time without date. For example, “12:59”.



211
212
213
# File 'lib/r18n-core/locale.rb', line 211

def format_time(time)
  strftime(time, @data['time']['time'])
end

#format_time_full(i18n, 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.



249
250
251
# File 'lib/r18n-core/locale.rb', line 249

def format_time_full(i18n, time)
  format_date_full(i18n, time) + format_time(time)
end

#format_time_human(i18n, time, now = Time.now) ⇒ 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.



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/r18n-core/locale.rb', line 218

def format_time_human(i18n, time, now = Time.now)
  minutes = (time - now) / 60.0
  if time.mday != now.mday and minutes.abs > 720 # 12 hours
    format_date_human(i18n, R18n::Utils.to_date(time),
                            R18n::Utils.to_date(now)) + format_time(time)
  else
    case minutes
    when -60..-1
      i18n.human_time.minutes_ago(minutes.round.abs)
    when 1..60
      i18n.human_time.after_minutes(minutes.round)
    when -1..1
      i18n.human_time.now
    else
      hours = (minutes / 60.0).abs.floor
      if time > now
        i18n.human_time.after_hours(hours)
      else
        i18n.human_time.hours_ago(hours)
      end
    end
  end
end

#format_time_standard(i18n, time) ⇒ Object

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



243
244
245
# File 'lib/r18n-core/locale.rb', line 243

def format_time_standard(i18n, time)
  format_date_standard(i18n, time) + format_time(time)
end

#inspectObject

Human readable locale code and title



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

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

#ltr?Boolean

Is locale has left-to-right write direction.

Returns:

  • (Boolean)


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

def ltr?
  @data['direction'] == 'ltr'
end

#pluralize(n) ⇒ Object

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



290
291
292
293
294
295
296
297
298
299
# File 'lib/r18n-core/locale.rb', line 290

def pluralize(n)
  case n
  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.



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 185

def strftime(time, format)
  translated = ''
  format.scan(/%[EO]?.|./o) do |c|
    case c.sub(/^%[EO]?(.)$/o, '%\\1')
    when '%A'
      translated << @data['week']['days'][time.wday]
    when '%a'
      translated << @data['week']['abbrs'][time.wday]
    when '%B'
      translated << @data['months']['names'][time.month - 1]
    when '%b'
      translated << @data['months']['abbrs'][time.month - 1]
    when '%p'
      translated << if time.hour < 12
        @data['time']['am']
      else
        @data['time']['pm']
      end
    else
      translated << c
    end
  end
  time.strftime(translated)
end

#supported?Boolean

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

Returns:

  • (Boolean)


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

def supported?
  true
end

#titleObject

Locale title.



134
135
136
# File 'lib/r18n-core/locale.rb', line 134

def title
  @data['title']
end