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, opts = {}) ⇒ 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.



143
144
145
146
147
148
149
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 143

def initialize(locales, translation_places = nil, opts = {})
  locales = Array(locales)

  if !locales.empty? && 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)

  @filters =
    if opts[:on_filters] || opts[:off_filters]
      CustomFilterList.new(opts[:on_filters], opts[:off_filters])
    else
      GlobalFilterList.instance
    end

  key = translation_cache_key
  if R18n.cache.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.



291
292
293
# File 'lib/r18n-core/i18n.rb', line 291

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

Instance Attribute Details

#localeObject (readonly)

First locale with locale file



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

def locale
  @locale
end

#localesObject (readonly)

User locales, ordered by priority



128
129
130
# File 'lib/r18n-core/i18n.rb', line 128

def locales
  @locales
end

#translation_placesObject (readonly)

Loaders with translations files



131
132
133
# File 'lib/r18n-core/i18n.rb', line 131

def translation_places
  @translation_places
end

Class Method Details

.convert_places(places) ⇒ Object

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



117
118
119
120
121
122
123
124
125
# File 'lib/r18n-core/i18n.rb', line 117

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

.defaultObject

Get default locale code



95
96
97
# File 'lib/r18n-core/i18n.rb', line 95

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.



90
91
92
# File 'lib/r18n-core/i18n.rb', line 90

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

.parse_http(str) ⇒ Object

Parse HTTP_ACCEPT_LANGUAGE and return array of user locales



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

def self.parse_http(str)
  return [] if str.nil?
  locales = str.split(',')
  locales.map! do |locale|
    locale = locale.split ';q='
    if locale.size == 1
      [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.



288
289
290
# File 'lib/r18n-core/i18n.rb', line 288

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

#available_localesObject

Return Array of locales with available translations.



257
258
259
# File 'lib/r18n-core/i18n.rb', line 257

def available_locales
  @available ||= R18n.available_locales(@translation_places)
end

#filter_listObject

Return custom filters list



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

def filter_list
  @filters
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 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.

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"


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

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

#reload!Object

Reload translations.



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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/r18n-core/i18n.rb', line 201

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 defined? @locale
    # It's array!
    # rubocop:disable Perfomance/HashEachMethods
    available_in_places.each do |_place, available|
      @locales.each do |locale|
        if available.include? locale
          @locale = locale
          break
        end
      end
      break if defined? @locale
    end
    # rubocop:enable Perfomance/HashEachMethods
  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, '', filters: @filters)
  @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

    next unless loaded

    available_in_extensions.each do |extension, available|
      if available.include? locale
        @translation.merge! extension.load(locale), locale
      end
    end
  end

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

#tObject

Return translations.



280
281
282
# File 'lib/r18n-core/i18n.rb', line 280

def t
  @translation
end

#translation_cache_keyObject

Return unique key for current locales in translation and places.



189
190
191
192
193
194
195
196
197
198
# File 'lib/r18n-core/i18n.rb', line 189

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(',') + '@' +
    @filters.hash.to_s + '_' +
    R18n.default_loader.hash.to_s + '_' +
    @translation_places.hash.to_s + '_' +
    R18n.extension_places.hash.to_s
end