分享 I18n 文案替换

lance_zyb · 2016年04月26日 · 最后由 mizuhashi 回复于 2016年04月26日 · 2350 次阅读

I18n 文案替换

file

who1 = "I am %{name}."
who2 = "I am %%{name}"

I18n.interpolate(who1, {name: "Tom"}) #=> "I am Tom"
I18n.interpolate(who1, {name: "Tom"}) #=> "I am %{name}"

1. 文案替换的思路为

a. 对 who1who2 进行分解,期望得到

split_who1 = ["I am ", "%{name}", "."] split_who2 = ["I am ", "%%{name}", "."]

b. Tome 替换 %{name}%%{name} 保留 %{name}

translate_who1 = "I am Tom." translate_who2 = "I am %{name}."

2. 分解字符串的源码

源代码

module Compiler
  TOKENIZER = /(%%\{[^\}]+\}|%\{[^\}]+\})/

  protected
  # tokenize("foo %{bar} baz %%{buz}") # => ["foo ", "%{bar}", " baz ", "%%{buz}"]
  def tokenize(str)
    str.split(TOKENIZER)
  end
end

正则表达式TOKENIZER分解:

  1. (%%\{[^\}]+\})(%\{[^\}]+\})
  2. [^\}]+表示 非 } 一个或一个以上的字符
  3. \{[^\{]+\} 表示匹配 {}非 }一个或一个以上的字符
  4. split方法,参数为Regexp()的字符会被保留

eg

a = "test & est"
a.split(/\&/) #=> ["test ", " test"]
a.split(/(\&)/) #=> ["test ", "&", " test"]

split_who1 = who1.split(/(%\{[^\}]+\})/) #=> ["I am ", "%{name}", "."]
split_who2 = who2.split(/(%%\{[^\}]+\})/) #=> ["I am ", "%%{name}", "."]

3. 替换字符串思路及源码

添加单例方法 who1.i18n_interpolate({name: "Tom"}) who2.i18n_interpolate({})

其中 who1i18n_interpolate 代码段为 "I am #{v{:name}}.",其中 v = {name: "Tom"} who2i18n_interpolate 代码段为 "I am %{name}"

主要的代码为:

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

其中

who1 等价于

def i18n_interpolate(v = {})
  str = (t = v[:name] && t.respond_to?(:call) ? t.call : t)
  ||
  (v.has_key?(:name) && '')
  ||
  Raise(MissingInterpolationArgument.new(:name, self))

  "I am #{str}"
end

who2 等价于

def i18n_interpolate(v = {})
  "I am %{name}"
end

不善于言语~只能贴代码!

完全看不懂~

需要 登录 后方可回复, 如果你还没有账号请 注册新账号