Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

122 lines (102 sloc) 3.755 kB
# The InterpolationCompiler module contains optimizations that can tremendously
# speed up the interpolation process on the Simple backend.
#
# It works by defining a pre-compiled method on stored translation Strings that
# already bring all the knowledge about contained interpolation variables etc.
# so that the actual recurring interpolation will be very fast.
#
# To enable pre-compiled interpolations you can simply include the
# InterpolationCompiler module to the Simple backend:
#
# I18n::Backend::Simple.send(:include, I18n::Backend::InterpolationCompiler)
#
# Note that InterpolationCompiler does not yield meaningful results and consequently
# should not be used with Ruby 1.9 (YARV) but improves performance everywhere else
# (jRuby, Rubinius and 1.8.7).
module I18n
module Backend
module InterpolationCompiler
module Compiler
extend self
TOKENIZER = /(%%\{[^\}]+\}|%\{[^\}]+\})/
INTERPOLATION_SYNTAX_PATTERN = /(%)?(%\{([^\}]+)\})/
def compile_if_an_interpolation(string)
if interpolated_str?(string)
string.instance_eval <<-RUBY_EVAL, __FILE__, __LINE__
def i18n_interpolate(v = {})
"#{compiled_interpolation_body(string)}"
end
RUBY_EVAL
end
string
end
def interpolated_str?(str)
str.kind_of?(::String) && str =~ INTERPOLATION_SYNTAX_PATTERN
end
protected
# tokenize("foo %{bar} baz %%{buz}") # => ["foo ", "%{bar}", " baz ", "%%{buz}"]
def tokenize(str)
str.split(TOKENIZER)
end
def compiled_interpolation_body(str)
tokenize(str).map do |token|
(matchdata = token.match(INTERPOLATION_SYNTAX_PATTERN)) ? handle_interpolation_token(token, matchdata) : escape_plain_str(token)
end.join
end
def handle_interpolation_token(interpolation, matchdata)
escaped, pattern, key = matchdata.values_at(1, 2, 3)
escaped ? pattern : compile_interpolation_token(key.to_sym)
end
def compile_interpolation_token(key)
"\#{#{interpolate_or_raise_missing(key)}}"
end
def interpolate_or_raise_missing(key)
escaped_key = escape_key_sym(key)
RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key)
end
def interpolate_key(key)
[direct_key(key), nil_key(key), missing_key(key)].join('||')
end
def direct_key(key)
"((t = v[#{key}]) && t.respond_to?(:call) ? t.call : t)"
end
def nil_key(key)
"(v.has_key?(#{key}) && '')"
end
def missing_key(key)
"raise(MissingInterpolationArgument.new(#{key}, self))"
end
def reserved_key(key)
"raise(ReservedInterpolationKey.new(#{key}, self))"
end
def escape_plain_str(str)
str.gsub(/"|\\|#/) {|x| "\\#{x}"}
end
def escape_key_sym(key)
# rely on Ruby to do all the hard work :)
key.to_sym.inspect
end
end
def interpolate(locale, string, values)
if string.respond_to?(:i18n_interpolate)
string.i18n_interpolate(values)
elsif values
super
else
string
end
end
def store_translations(locale, data, options = {})
compile_all_strings_in(data)
super
end
protected
def compile_all_strings_in(data)
data.each_value do |value|
Compiler.compile_if_an_interpolation(value)
compile_all_strings_in(value) if value.kind_of?(Hash)
end
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.