This file is indexed.

/usr/lib/ruby/vendor_ruby/i18n.rb is in ruby-i18n 0.7.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
173
174
175
176
177
178
179
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
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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
require 'i18n/version'
require 'i18n/exceptions'
require 'i18n/interpolate/ruby'

module I18n
  autoload :Backend, 'i18n/backend'
  autoload :Config,  'i18n/config'
  autoload :Gettext, 'i18n/gettext'
  autoload :Locale,  'i18n/locale'
  autoload :Tests,   'i18n/tests'

  RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :throw, :raise]
  RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/

  extend(Module.new {
    # Gets I18n configuration object.
    def config
      Thread.current[:i18n_config] ||= I18n::Config.new
    end

    # Sets I18n configuration object.
    def config=(value)
      Thread.current[:i18n_config] = value
    end

    # Write methods which delegates to the configuration object
    %w(locale backend default_locale available_locales default_separator
      exception_handler load_path enforce_available_locales).each do |method|
      module_eval <<-DELEGATORS, __FILE__, __LINE__ + 1
        def #{method}
          config.#{method}
        end

        def #{method}=(value)
          config.#{method} = (value)
        end
      DELEGATORS
    end

    # Tells the backend to reload translations. Used in situations like the
    # Rails development environment. Backends can implement whatever strategy
    # is useful.
    def reload!
      config.clear_available_locales_set
      config.backend.reload!
    end

    # Translates, pluralizes and interpolates a given key using a given locale,
    # scope, and default, as well as interpolation values.
    #
    # *LOOKUP*
    #
    # Translation data is organized as a nested hash using the upper-level keys
    # as namespaces. <em>E.g.</em>, ActionView ships with the translation:
    # <tt>:date => {:formats => {:short => "%b %d"}}</tt>.
    #
    # Translations can be looked up at any level of this hash using the key argument
    # and the scope option. <em>E.g.</em>, in this example <tt>I18n.t :date</tt>
    # returns the whole translations hash <tt>{:formats => {:short => "%b %d"}}</tt>.
    #
    # Key can be either a single key or a dot-separated key (both Strings and Symbols
    # work). <em>E.g.</em>, the short format can be looked up using both:
    #   I18n.t 'date.formats.short'
    #   I18n.t :'date.formats.short'
    #
    # Scope can be either a single key, a dot-separated key or an array of keys
    # or dot-separated keys. Keys and scopes can be combined freely. So these
    # examples will all look up the same short date format:
    #   I18n.t 'date.formats.short'
    #   I18n.t 'formats.short', :scope => 'date'
    #   I18n.t 'short', :scope => 'date.formats'
    #   I18n.t 'short', :scope => %w(date formats)
    #
    # *INTERPOLATION*
    #
    # Translations can contain interpolation variables which will be replaced by
    # values passed to #translate as part of the options hash, with the keys matching
    # the interpolation variable names.
    #
    # <em>E.g.</em>, with a translation <tt>:foo => "foo %{bar}"</tt> the option
    # value for the key +bar+ will be interpolated into the translation:
    #   I18n.t :foo, :bar => 'baz' # => 'foo baz'
    #
    # *PLURALIZATION*
    #
    # Translation data can contain pluralized translations. Pluralized translations
    # are arrays of singluar/plural versions of translations like <tt>['Foo', 'Foos']</tt>.
    #
    # Note that <tt>I18n::Backend::Simple</tt> only supports an algorithm for English
    # pluralization rules. Other algorithms can be supported by custom backends.
    #
    # This returns the singular version of a pluralized translation:
    #   I18n.t :foo, :count => 1 # => 'Foo'
    #
    # These both return the plural version of a pluralized translation:
    #   I18n.t :foo, :count => 0 # => 'Foos'
    #   I18n.t :foo, :count => 2 # => 'Foos'
    #
    # The <tt>:count</tt> option can be used both for pluralization and interpolation.
    # <em>E.g.</em>, with the translation
    # <tt>:foo => ['%{count} foo', '%{count} foos']</tt>, count will
    # be interpolated to the pluralized translation:
    #   I18n.t :foo, :count => 1 # => '1 foo'
    #
    # *DEFAULTS*
    #
    # This returns the translation for <tt>:foo</tt> or <tt>default</tt> if no translation was found:
    #   I18n.t :foo, :default => 'default'
    #
    # This returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt> if no
    # translation for <tt>:foo</tt> was found:
    #   I18n.t :foo, :default => :bar
    #
    # Returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt>
    # or <tt>default</tt> if no translations for <tt>:foo</tt> and <tt>:bar</tt> were found.
    #   I18n.t :foo, :default => [:bar, 'default']
    #
    # *BULK LOOKUP*
    #
    # This returns an array with the translations for <tt>:foo</tt> and <tt>:bar</tt>.
    #   I18n.t [:foo, :bar]
    #
    # Can be used with dot-separated nested keys:
    #   I18n.t [:'baz.foo', :'baz.bar']
    #
    # Which is the same as using a scope option:
    #   I18n.t [:foo, :bar], :scope => :baz
    #
    # *LAMBDAS*
    #
    # Both translations and defaults can be given as Ruby lambdas. Lambdas will be
    # called and passed the key and options.
    #
    # E.g. assuming the key <tt>:salutation</tt> resolves to:
    #   lambda { |key, options| options[:gender] == 'm' ? "Mr. %{options[:name]}" : "Mrs. %{options[:name]}" }
    #
    # Then <tt>I18n.t(:salutation, :gender => 'w', :name => 'Smith') will result in "Mrs. Smith".
    #
    # It is recommended to use/implement lambdas in an "idempotent" way. E.g. when
    # a cache layer is put in front of I18n.translate it will generate a cache key
    # from the argument values passed to #translate. Therefor your lambdas should
    # always return the same translations/values per unique combination of argument
    # values.
    def translate(*args)
      options  = args.last.is_a?(Hash) ? args.pop.dup : {}
      key      = args.shift
      backend  = config.backend
      locale   = options.delete(:locale) || config.locale
      handling = options.delete(:throw) && :throw || options.delete(:raise) && :raise # TODO deprecate :raise

      enforce_available_locales!(locale)
      raise I18n::ArgumentError if key.is_a?(String) && key.empty?

      result = catch(:exception) do
        if key.is_a?(Array)
          key.map { |k| backend.translate(locale, k, options) }
        else
          backend.translate(locale, key, options)
        end
      end
      result.is_a?(MissingTranslation) ? handle_exception(handling, result, locale, key, options) : result
    end
    alias :t :translate

    # Wrapper for <tt>translate</tt> that adds <tt>:raise => true</tt>. With
    # this option, if no translation is found, it will raise <tt>I18n::MissingTranslationData</tt>
    def translate!(key, options={})
      translate(key, options.merge(:raise => true))
    end
    alias :t! :translate!

    # Returns true if a translation exists for a given key, otherwise returns false.
    def exists?(key, locale = config.locale)
      raise I18n::ArgumentError if key.is_a?(String) && key.empty?
      config.backend.exists?(locale, key)
    end

    # Transliterates UTF-8 characters to ASCII. By default this method will
    # transliterate only Latin strings to an ASCII approximation:
    #
    #    I18n.transliterate("Ærøskøbing")
    #    # => "AEroskobing"
    #
    #    I18n.transliterate("日本語")
    #    # => "???"
    #
    # It's also possible to add support for per-locale transliterations. I18n
    # expects transliteration rules to be stored at
    # <tt>i18n.transliterate.rule</tt>.
    #
    # Transliteration rules can either be a Hash or a Proc. Procs must accept a
    # single string argument. Hash rules inherit the default transliteration
    # rules, while Procs do not.
    #
    # *Examples*
    #
    # Setting a Hash in <locale>.yml:
    #
    #    i18n:
    #      transliterate:
    #        rule:
    #          ü: "ue"
    #          ö: "oe"
    #
    # Setting a Hash using Ruby:
    #
    #     store_translations(:de, :i18n => {
    #       :transliterate => {
    #         :rule => {
    #           "ü" => "ue",
    #           "ö" => "oe"
    #         }
    #       }
    #     )
    #
    # Setting a Proc:
    #
    #     translit = lambda {|string| MyTransliterator.transliterate(string) }
    #     store_translations(:xx, :i18n => {:transliterate => {:rule => translit})
    #
    # Transliterating strings:
    #
    #     I18n.locale = :en
    #     I18n.transliterate("Jürgen") # => "Jurgen"
    #     I18n.locale = :de
    #     I18n.transliterate("Jürgen") # => "Juergen"
    #     I18n.transliterate("Jürgen", :locale => :en) # => "Jurgen"
    #     I18n.transliterate("Jürgen", :locale => :de) # => "Juergen"
    def transliterate(*args)
      options      = args.pop.dup if args.last.is_a?(Hash)
      key          = args.shift
      locale       = options && options.delete(:locale) || config.locale
      handling     = options && (options.delete(:throw) && :throw || options.delete(:raise) && :raise)
      replacement  = options && options.delete(:replacement)
      enforce_available_locales!(locale)
      config.backend.transliterate(locale, key, replacement)
    rescue I18n::ArgumentError => exception
      handle_exception(handling, exception, locale, key, options || {})
    end

    # Localizes certain objects, such as dates and numbers to local formatting.
    def localize(object, options = nil)
      options = options ? options.dup : {}
      locale = options.delete(:locale) || config.locale
      format = options.delete(:format) || :default
      enforce_available_locales!(locale)
      config.backend.localize(locale, object, format, options)
    end
    alias :l :localize

    # Executes block with given I18n.locale set.
    def with_locale(tmp_locale = nil)
      if tmp_locale
        current_locale = self.locale
        self.locale    = tmp_locale
      end
      yield
    ensure
      self.locale = current_locale if tmp_locale
    end

    # Merges the given locale, key and scope into a single array of keys.
    # Splits keys that contain dots into multiple keys. Makes sure all
    # keys are Symbols.
    def normalize_keys(locale, key, scope, separator = nil)
      separator ||= I18n.default_separator

      keys = []
      keys.concat normalize_key(locale, separator)
      keys.concat normalize_key(scope, separator)
      keys.concat normalize_key(key, separator)
      keys
    end

    # Returns true when the passed locale, which can be either a String or a
    # Symbol, is in the list of available locales. Returns false otherwise.
    def locale_available?(locale)
      I18n.config.available_locales_set.include?(locale)
    end

    # Raises an InvalidLocale exception when the passed locale is not available.
    def enforce_available_locales!(locale)
      if config.enforce_available_locales
        raise I18n::InvalidLocale.new(locale) if !locale_available?(locale)
      end
    end

  private

    # Any exceptions thrown in translate will be sent to the @@exception_handler
    # which can be a Symbol, a Proc or any other Object unless they're forced to
    # be raised or thrown (MissingTranslation).
    #
    # If exception_handler is a Symbol then it will simply be sent to I18n as
    # a method call. A Proc will simply be called. In any other case the
    # method #call will be called on the exception_handler object.
    #
    # Examples:
    #
    #   I18n.exception_handler = :custom_exception_handler              # this is the default
    #   I18n.custom_exception_handler(exception, locale, key, options)  # will be called like this
    #
    #   I18n.exception_handler = lambda { |*args| ... }                 # a lambda
    #   I18n.exception_handler.call(exception, locale, key, options)    # will be called like this
    #
    #   I18n.exception_handler = I18nExceptionHandler.new               # an object
    #   I18n.exception_handler.call(exception, locale, key, options)    # will be called like this
    def handle_exception(handling, exception, locale, key, options)
      case handling
      when :raise
        raise exception.respond_to?(:to_exception) ? exception.to_exception : exception
      when :throw
        throw :exception, exception
      else
        case handler = options[:exception_handler] || config.exception_handler
        when Symbol
          send(handler, exception, locale, key, options)
        else
          handler.call(exception, locale, key, options)
        end
      end
    end

    def normalize_key(key, separator)
      normalized_key_cache[separator][key] ||=
        case key
        when Array
          key.map { |k| normalize_key(k, separator) }.flatten
        else
          keys = key.to_s.split(separator)
          keys.delete('')
          keys.map! { |k| k.to_sym }
          keys
        end
    end

    def normalized_key_cache
      @normalized_key_cache ||= Hash.new { |h,k| h[k] = {} }
    end
  })
end