Class: R18n::I18n

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

Overview

General class to i18n support in your application. It load Translation and Locale classes and create pretty way to use it.

To get translation you can use same with Translation way – use method with translation’s name or [name] method. Translations will be also loaded for default locale, sublocales from first in locales and general languages for dialects (it will load fr for fr_CA too).

Translations will loaded by loader object, which must have 2 methods:

  • available – return array of locales of available translations;

  • load(locale) – return Hash of translation.

If you will use default loader (R18n.default_loader) you can pass to I18n only constructor argument for loader:

R18n::I18n.new('en', R18n::Loader::YAML.new('dir/with/translations'))

is a same as:

R18n::I18n.new('en', 'dir/with/translations')

In translation file you can use strings, numbers, floats (any YAML types) and pluralizable values (!!pl). You can use params in string values, which you can replace in program. Just write %1, %2, etc and set it values as method arguments, when you will be get value.

You can use filters for some YAML type or for all strings. See R18n::Filters for details.

R18n contain translations for common words (such as “OK”, “Cancel”, etc) for most supported locales. See base/ dir.

Usage

translations/ru.yml

one: Один

translations/en.yml

one: One
two: Two

example.rb

i18n = R18n::I18n.new(['ru', 'en'], 'translations/')

i18n.one   #=> "Один"
i18n.two   #=> "Two"

i18n.locale.title        #=> "Русский"
i18n.locale.code         #=> "ru"
i18n.locale.ltr?         #=> true

i18n.l -11000.5          #=> "−11 000,5"
i18n.l Time.now          #=> "Вск, 21 сен 2008, 22:10:10 MSD"
i18n.l Time.now, :date   #=> "21.09.2008"
i18n.l Time.now, :time   #=> "22:10"
i18n.l Time.now, '%A'    #=> "Воскресенье"

i18n.yes    #=> "Yes"
i18n.ok     #=> "OK"
i18n.cancel #=> "Cancel"

Constant Summary collapse

@@default =
'en'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(locales, translation_places = nil) ⇒ I18n

Create i18n for locales with translations from translation_places and locales data. Translations will be also loaded for default locale, sublocales from first in locales and general languages for dialects (it will load fr for fr_CA too).

Locales must be a locale code (RFC 3066) or array, ordered by priority. Translation_places must be a string with path or array.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/r18n-core/i18n.rb', line 150

def initialize(locales, translation_places = nil)
  locales = Array(locales)

  if not locales.empty? and Locale.exists? locales.first
    locales += Locale.load(locales.first).sublocales
  end
  locales << @@default
  locales.each_with_index do |locale, i|
    if locale =~ /[_-]/
      locales.insert(i + 1, locale.match(/([^_-]+)[_-]/)[1])
    end
  end
  locales.map! { |i| i.to_s.downcase }.uniq!
  @locales_codes = locales
  @locales = locales.map { |i| Locale.load(i) }

  if translation_places
    @original_places = translation_places
  else
    @original_places = R18n.extension_places
    @locale = @locales.first
  end

  @translation_places = self.class.convert_places(@original_places)

  key = translation_cache_key
  if R18n.cache.has_key? key
    @locale, @translation = *R18n.cache[key]
  else
    reload!
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missingObject

Return translation with special name.

Translation can contain variable part. Just set is as %1, %2, etc in translations file and set values in next params.



277
278
279
# File 'lib/r18n-core/i18n.rb', line 277

def [](name, *params)
  @translation[name, *params]
end

Instance Attribute Details

#localeObject (readonly)

First locale with locale file



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

def locale
  @locale
end

#localesObject (readonly)

User locales, ordered by priority



135
136
137
# File 'lib/r18n-core/i18n.rb', line 135

def locales
  @locales
end

#translation_placesObject (readonly)

Loaders with translations files



138
139
140
# File 'lib/r18n-core/i18n.rb', line 138

def translation_places
  @translation_places
end

Class Method Details

.available_locales(places) ⇒ Object

Return Array of locales with available translations.



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

def self.available_locales(places)
  convert_places(places).map { |i| i.available }.flatten.uniq
end

.convert_places(places) ⇒ Object

Load default loader for elements in places with only constructor argument.



124
125
126
127
128
129
130
131
132
# File 'lib/r18n-core/i18n.rb', line 124

def self.convert_places(places)
  Array(places).map! do |loader|
    if loader.respond_to? :available and loader.respond_to? :load
      loader
    else
      R18n.default_loader.new(loader)
    end
  end
end

.defaultObject

Get default locale code



97
98
99
# File 'lib/r18n-core/i18n.rb', line 97

def self.default
  @@default
end

.default=(locale) ⇒ Object

Set default locale code to use when any user locales willn’t be founded. It should has all translations and locale file.



92
93
94
# File 'lib/r18n-core/i18n.rb', line 92

def self.default=(locale)
  @@default = locale
end

.parse_http(str) ⇒ Object

Parse HTTP_ACCEPT_LANGUAGE and return array of user locales



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/r18n-core/i18n.rb', line 102

def self.parse_http(str)
  return [] if str.nil?
  locales = str.split(',')
  locales.map! do |locale|
    locale = locale.split ';q='
    if 1 == locale.size
      [locale[0], 1.0]
    else
      [locale[0], locale[1].to_f]
    end
  end
  locales.sort! { |a, b| b[1] <=> a[1] }
  locales.map! { |i| i[0] }
end

Instance Method Details

#[](name, *params) ⇒ Object Also known as: method_missing

Return translation with special name.

Translation can contain variable part. Just set is as %1, %2, etc in translations file and set values in next params.



274
275
276
# File 'lib/r18n-core/i18n.rb', line 274

def [](name, *params)
  @translation[name, *params]
end

#available_localesObject

Return Array of locales with available translations.



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

def available_locales
  @available ||= self.class.available_locales(@translation_places)
end

#localize(object, format = nil, *params) ⇒ Object Also known as: l

Convert object to String, according to the rules of the current locale. It support Fixnum, Bignum, 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.

i18n.l -12000.5         #=> "−12,000.5"
i18n.l Time.now         #=> "07/01/09 12:59"
i18n.l Time.now.to_date #=> "07/01/09"
i18n.l Time.now, :human #=> "now"
i18n.l Time.now, :full  #=> "Jule 1st, 2009 12:59"


260
261
262
# File 'lib/r18n-core/i18n.rb', line 260

def localize(object, format = nil, *params)
  locale.localize(object, format, self, *params)
end

#reload!Object

Reload translations.



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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/i18n.rb', line 193

def reload!
  @available = @available_codes = nil
  @translation_places = self.class.convert_places(@original_places)

  available_in_places = @translation_places.map { |i| [i, i.available] }
  available_in_extensions = R18n.extension_places.map {|i| [i, i.available]}

  unless @locale
    available_in_places.each do |place, available|
      @locales.each do |locale|
        if available.include? locale
          @locale = locale
          break
        end
      end
      break if @locale
    end
  end
  @locale ||= @locales.first
  unless @locale.supported?
    @locales.each do |locale|
      if locale.supported?
        @locale.base = locale
        break
      end
    end
  end

  @translation = Translation.new @locale
  @locales.each do |locale|
    loaded = false
    available_in_places.each do |place, available|
      if available.include? locale
        @translation.merge! place.load(locale), locale
        loaded = true
      end
    end
    if loaded
      available_in_extensions.each do |extension, available|
        if available.include? locale
          @translation.merge! extension.load(locale), locale
        end
      end
    end
  end

  R18n.cache[translation_cache_key] = [@locale, @translation]
end

#tObject

Return translations.



266
267
268
# File 'lib/r18n-core/i18n.rb', line 266

def t
  @translation
end

#translation_cache_keyObject

Return unique key for current locales in translation and places.



184
185
186
187
188
189
190
# File 'lib/r18n-core/i18n.rb', line 184

def translation_cache_key
  @available_codes ||= @translation_places.inject([]) { |all, i|
    all + i.available }.uniq.map { |i| i.code.downcase }
  (@locales_codes & @available_codes).join(',') + '@' +
    R18n.default_loader.hash.to_s +
    @translation_places.hash.to_s + R18n.extension_places.hash.to_s
end