Rails I18n翻译范围

时间:2015-02-18 23:22:21

标签: ruby-on-rails ruby scope erb rails-i18n

编写完全翻译的应用程序可能会变得单调乏味。有没有办法为当前上下文设置默认的翻译范围?

示例:我在ProjectsController

show.html.erb 操作中写了部分 _deadlines.html.erb

现在,因为我想成为一名优秀的程序员,所以我的所有翻译都是如此。我想生成以下树

projects:
  deadlines:
    now: "Hurry the deadline is today !"
    ....

如果每次写完整个范围,我怎样才能减少繁琐?

项目/ show.html.erb

...
<%= render 'projects/deadlines', project: @project %>
...
show.html.erb

调用的

projects / _deadlines.html.erb

<p>Deadline : <%= t(:now, scope: [:projects, :deadlines]) %></p>

有没有办法为当前上下文设置默认范围(这里是整个 _deadlines.html.erb 文件)?

编辑

有人建议使用Rails Lazy lookup,但这不会产生我正在寻找的范围。在我的情况下,我想跳过action默认范围(显示,索引等等)并为我正在呈现的当前部分添加范围(在我的情况下为_deadlines.html.erb)

Rails懒惰查找:

t('.now')
<=> t(:now, scope: [:projects, :show]

但我想:

t('.now')
<=> t(:now, scope: [:projects, :deadlines]

3 个答案:

答案 0 :(得分:4)

Rails实现了在视图中查找区域设置的便捷方式。 如果您有以下字典:

es:
  projects:
    index:  # in 'index.html.erb' template file
      title: "Título"
    deadlines:  # in '_deadlines.html.erb' partial file
      title: "Fecha límite"

您可以按以下方式查找这些值:

# app/views/projects/index.html.erb
<%= t '.title' %>  # => "Título"

# app/views/projects/_deadlines.html.erb
<%= t '.title' %>  # => "Fecha límite"

答案 1 :(得分:1)

好吧,我真的对此仍不满意。这个默认的懒惰查找&#39;当你想在不同的地方翻译同样的东西时,范围完全是废话。假设我有两个不同的部分包含处理相同模型的信息。使用延迟查找,我需要在我的yml文件中进行两次相同的翻译。

这是您可以在应用程序助手中添加的一小段代码。它基本上是默认I18n.t的覆盖,它会在定义时将范围设置为@t_scope,并且您不再需要担心范围

我的代码添加

助手/ application_helper.rb

def t(*args)
  # If there is just one param and we have defined a translation scope in the view
  # only using symbols right now, need extended version to handle strings
  if args.size == 1 and args.first.is_a?(Symbol) and @t_scope
    super(args.shift, @t_scope)
  else
    super(*args)
  end
end

def set_t_scope(scope)
  push_t_scope(@t_scope ||= {})
  replace_t_scope(scope)
end
alias :t_scope :set_t_scope

def replace_t_scope(scope)
  @t_scope = {scope: scope}
end

def push_t_scope(scope)
  (@tscope_stack ||= []) << scope
end

def pop_t_scope
  @t_scope = @tscope_stack.pop
end

您可以用它做什么

项目/ show.html.erb

<%= t_scope([:projects, :deadlines]) %>
<fieldset>
  <legend>Deadlines</legend>
  <% if Time.now > @project.deadline.expected_finish_date %>
  <p><%= t(:hurry) %></p>
  <% else %>
  <p><%= t(:you_have_time) %>
</fieldset>
<fieldset>
  <legend>Deadlines</legend>
  <%= render 'tasks', tasks: @project.tasks %>
...

视图/项目/ _tasks.html.erb

<%= t_scope([:projects, :tasks]) %>
  <% tasks.each do | task| %>
  <h2><%= t(:person_in_charge) %></h2>
  ...
<% pop_t_scope %>  

en.yml

en:
  projects:
    deadlines:
      hurry: "Hurry man !"
      you_have_time: "Relax, there's still time"
    tasks:
      person_in_charge: 'The Boss is %{name}'

现在我看到的唯一问题是,当从视图渲染多个部分时,@ t_scope将被转移并可能导致问题。然而,在每个文件的开头将@t_scope设置为nil不会有问题

答案 2 :(得分:0)

由于 t('.foo') 是可能的并且可能有选项(例如插值),这里是我改进 the previous one 的提议

def t(*args, **kwargs)
  if args.size == 1 and (args.first.is_a?(Symbol) || args.first.to_s.start_with?('.') ) and @t_scope
    I18n.t(args.shift, kwargs.reverse_merge!(@t_scope))
  else
    I18n.t(*args)
  end
end