File: active_support/vendor/i18n-0.4.1/i18n/backend/interpolation_compiler.rb

Overview
Module Structure
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: I18n#18
  module: Backend#19
  module: InterpolationCompiler#20
has properties
method: interpolate / 3 #99
method: store_translations / 3 #109
method: compile_all_strings_in / 1 #115
  module: Compiler#21
extends
  Compiler ( I18n::Backend::InterpolationCompiler )
has properties
constant: TOKENIZER #24
constant: INTERPOLATION_SYNTAX_PATTERN #25
method: compile_if_an_interpolation / 1 #27
method: interpolated_str? / 1 #39
method: tokenize / 1 #45
method: compiled_interpolation_body / 1 #49
method: handle_interpolation_token / 2 #55
method: compile_interpolation_token / 1 #60
method: interpolate_or_raise_missing / 1 #64
method: interpolate_key / 1 #69
method: direct_key / 1 #73
method: nil_key / 1 #77
method: missing_key / 1 #81
method: reserved_key / 1 #85
method: escape_plain_str / 1 #89
method: escape_key_sym / 1 #93

Code

   1  # encoding: utf-8
   2 
   3  # The InterpolationCompiler module contains optimizations that can tremendously
   4  # speed up the interpolation process on the Simple backend.
   5  #
   6  # It works by defining a pre-compiled method on stored translation Strings that
   7  # already bring all the knowledge about contained interpolation variables etc.
   8  # so that the actual recurring interpolation will be very fast.
   9  #
  10  # To enable pre-compiled interpolations you can simply include the
  11  # InterpolationCompiler module to the Simple backend:
  12  #
  13  #   I18n::Backend::Simple.send(:include, I18n::Backend::InterpolationCompiler)
  14  #
  15  # Note that InterpolationCompiler does not yield meaningful results and consequently
  16  # should not be used with Ruby 1.9 (YARV) but improves performance everywhere else
  17  # (jRuby, Rubinius and 1.8.7).
  18  module I18n
  19    module Backend
  20      module InterpolationCompiler
  21        module Compiler
  22          extend self
  23 
  24          TOKENIZER                    = /(%%\{[^\}]+\}|%\{[^\}]+\})/
  25          INTERPOLATION_SYNTAX_PATTERN = /(%)?(%\{([^\}]+)\})/
  26 
  27          def compile_if_an_interpolation(string)
  28            if interpolated_str?(string)
  29              string.instance_eval <<-RUBY_EVAL, __FILE__, __LINE__
  30                def i18n_interpolate(v = {})
  31                  "#{compiled_interpolation_body(string)}"
  32                end
  33              RUBY_EVAL
  34            end
  35 
  36            string
  37          end
  38 
  39          def interpolated_str?(str)
  40            str.kind_of?(::String) && str =~ INTERPOLATION_SYNTAX_PATTERN
  41          end
  42 
  43          protected
  44          # tokenize("foo %{bar} baz %%{buz}") # => ["foo ", "%{bar}", " baz ", "%%{buz}"]
  45          def tokenize(str)
  46            str.split(TOKENIZER)
  47          end
  48 
  49          def compiled_interpolation_body(str)
  50            tokenize(str).map do |token|
  51              (matchdata = token.match(INTERPOLATION_SYNTAX_PATTERN)) ? handle_interpolation_token(token, matchdata) : escape_plain_str(token)
  52            end.join
  53          end
  54 
  55          def handle_interpolation_token(interpolation, matchdata)
  56            escaped, pattern, key = matchdata.values_at(1, 2, 3)
  57            escaped ? pattern : compile_interpolation_token(key.to_sym)
  58          end
  59 
  60          def compile_interpolation_token(key)
  61            "\#{#{interpolate_or_raise_missing(key)}}"
  62          end
  63 
  64          def interpolate_or_raise_missing(key)
  65            escaped_key = escape_key_sym(key)
  66            Base::RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key)
  67          end
  68 
  69          def interpolate_key(key)
  70            [direct_key(key), nil_key(key), missing_key(key)].join('||')
  71          end
  72 
  73          def direct_key(key)
  74            "((t = v[#{key}]) && t.respond_to?(:call) ? t.call : t)"
  75          end
  76 
  77          def nil_key(key)
  78            "(v.has_key?(#{key}) && '')"
  79          end
  80 
  81          def missing_key(key)
  82            "raise(MissingInterpolationArgument.new(#{key}, self))"
  83          end
  84 
  85          def reserved_key(key)
  86            "raise(ReservedInterpolationKey.new(#{key}, self))"
  87          end
  88 
  89          def escape_plain_str(str)
  90            str.gsub(/"|\\|#/) {|x| "\\#{x}"}
  91          end
  92 
  93          def escape_key_sym(key)
  94            # rely on Ruby to do all the hard work :)
  95            key.to_sym.inspect
  96          end
  97        end
  98 
  99        def interpolate(locale, string, values)
 100          if string.respond_to?(:i18n_interpolate)
 101            string.i18n_interpolate(values)
 102          elsif values
 103            super
 104          else
 105            string
 106          end
 107        end
 108 
 109        def store_translations(locale, data, options = {})
 110          compile_all_strings_in(data)
 111          super
 112        end
 113 
 114        protected
 115        def compile_all_strings_in(data)
 116          data.each_value do |value|
 117            Compiler.compile_if_an_interpolation(value)
 118            compile_all_strings_in(value) if value.kind_of?(Hash)
 119          end
 120        end
 121      end
 122    end
 123  en