Class: Rubi18n::Translation

Inherits:
Object
  • Object
show all
Defined in:
lib/rubi18n/translation.rb

Overview

Translation for interface to i18n support.

Translation files use YAML format and has name CODE.yml, where CODE is a language/country code (RFC 3066) like en_US. For example: en.yaml is a English translation, en_US.yml is a translation to USA English dialect.

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

You may load several locales. Also for each locale will be load it sublocales – languages, which user often know in this locale. For example, many, who speak on Frensh dialects in Canada can understand original French. Also many people in Belarus can understand Russian.

Translated strinsg will have locale methods, which return Locale of locale code if locale info file isn’t exists.

Examples

translations/fr.yaml

one: Un

translations/ru.yaml

one: Один
two: Два

translations/en.yaml

one: One
two: Two
three: Three

entry:
  between: Between %1 and %2
methods: Is %1 method

comments: !!pl
  0: no comments
  1: one comment
  n: %1 comments

sum: !!proc |x, y| "is #{x + y}"

example.rb

i18n = Rubi18n::Translation.load(["fr", "ru"], "translations/")
i18n.one   #=> "Un"
i18n.two   #=> "Два"
i18n.three #=> "Three"

i18n.three.locale["code"]      #=> "en"
i18n.three.locale["direction"] #=> "ltr"

i18n.entry.between(2, 3)    #=> "between 2 and 3"
i18n["methods", "object"]   #=> "Is object method"

i18n.comments(0)            #=> "no comments"
i18n.comments(10)           #=> "10 comments"

i18n.sum(2, 3) #=> "is 5"

Extention translations

You can add dir with translations, which will be used with application translations. If application translations with same locale isn’t exists extention files willn’t be used.

It’s useful for plugins for rubi18n. For example DB plugin may place translations for error messages in extention dir. Rubi18n contain translations for base words as extention dir too.

Constant Summary collapse

@@default =
"en"
@@extension_translations =
[
Pathname(__FILE__).dirname.expand_path + "../../base"]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(locales, translations) ⇒ Translation

Create translation hash with messages in translations for locales.

This is internal contructor to load translation use Rubi18n::Translation.load(locales, translations_dir).



183
184
185
186
# File 'lib/rubi18n/translation.rb', line 183

def initialize(locales, translations)
  @locales = locales
  @translations = translations
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *params) ⇒ Object

Short and pretty way to get traslation by method name. If translation has name of object methods (“methods”, “strftime”) use [] method to access.

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



194
195
196
# File 'lib/rubi18n/translation.rb', line 194

def method_missing(name, *params)
  self[name.to_s, *params]
end

Class Method Details

.available(translations_dir) ⇒ Object

Return available translations in translations_dir



118
119
120
121
122
# File 'lib/rubi18n/translation.rb', line 118

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

.defaultObject

Get default locale code



104
105
106
# File 'lib/rubi18n/translation.rb', line 104

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.



99
100
101
# File 'lib/rubi18n/translation.rb', line 99

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

.extension_translationsObject

Get dirs with extention translations. If application translations with same locale isn’t exists extention files willn’t be used.



113
114
115
# File 'lib/rubi18n/translation.rb', line 113

def self.extension_translations
  @@extension_translations
end

.load(locales, translations_dir) ⇒ Object

Load locale and translations. locales may be string for one user locale or array with many.

It load all available translations in translations_dir, which exists in locales. Next it load all translations for sublocales in locale info for all loaded translations.

Example

locales is [“fr”, “uk”], translations are available for “fr”, “be”, “ru” and “en”. Translation will be founding firstly in “fr” next in “be” and next in “ru” and “en” (because many Belarusians know Russian and “be” locale contain in sublocales “ru” and “en”).



136
137
138
139
140
141
142
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
# File 'lib/rubi18n/translation.rb', line 136

def self.load(locales, translations_dir)
  locales = locales.to_a if Array != locales.class
  locales = locales + [@@default]
  
  locales += Locale.find(locales)["sublocales"]
  locales.each_with_index do |locale, i|
    # Add language locale for dialects
    if "_" == locale[2..2]
      locales.insert(i + 1, locale[0..1])
    end
  end
  locales.uniq!
  
  locales &= self.available(translations_dir)
  
  translations = []
  locales.map! do |locale|
    locale.delete!("/", "\\")
    
    translation = {}
    @@extension_translations.each do |dir|
      file = File.join(dir, "#{locale}.yml")
      translation.merge! YAML::load_file(file) if File.exists? file
    end
    file = File.join(translations_dir, "#{locale}.yml")
    translation.merge! YAML::load_file(file)
    translations << translation
    
    if Locale.exists? locale
      Locale.new(locale)
    else
      locale
    end
  end
  
  self.new(locales, translations)
end

.pluralize(n) ⇒ Object

Default pluralization rule to translation without locale info



175
176
177
# File 'lib/rubi18n/translation.rb', line 175

def self.pluralize(n)
  n == 0 ? 0 : n == 1 ? 1 : 'n'
end

Instance Method Details

#[](name, *params) ⇒ Object

Return traslation with special name.

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



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
# File 'lib/rubi18n/translation.rb', line 202

def [](name, *params)
  @translations.each_with_index do |translation, i|
    result = translation[name]
    next if result.nil?
    
    if YAML::PrivateType == result.class
      case result.type_id
      when "proc"
        return eval("proc {#{result.value}}").call(*params)
      when "pl"
        pluralizator = @locales[i]
        pluralizator = self.class if Locale != pluralizator.class
        
        params.each do |param|
          type = pluralizator.pluralize(param)
          type = "n" if not result.value.include? type
          result = result.value[type]
          break if YAML::PrivateType != result.class
        end
      else
        return result
      end
    end
    
    if String == result.class
      params.each_with_index do |param, i|
        result.gsub! "%#{i+1}", param.to_s
      end
      return TranslatedString.new(result, @locales[i])
    elsif Hash == result.class
      return self.class.new(@locales, @translations.map { |i|
        i[name] or {}
      })
    else
      return result
    end
  end
  
  return nil
end

#strftime(time, format) ⇒ Object

Format time according to the directives in the given format string and translate month, week days and meridian indicator (AM/PM) names (%A, %a, %B, %b, %p directives).

See Time.strftime() method docs for info about all directives.



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/rubi18n/translation.rb', line 248

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