铁路i18n – 翻译文本与链接里面
我想要一个看起来像这样的文字:
已经注册? login!
请注意,文字上有一个链接。 在这个例子中它指向谷歌 – 实际上它将指向我的应用程序的log_in_path
。
我发现了两种方法,但是没有一个看起来“正确”。
我知道的第一个方法是把这个我的en.yml
:
log_in_message: "Already signed up? <a href='{{url}}'>Log in!</a>"
在我看来:
<p> <%= t('log_in_message', :url => login_path) %> </p>
这是有效的 ,但是在<a href=...</a>
上有<a href=...</a>
部分对我来说看起来不是很干净。
我知道的另一个select是使用本地化的意见 – login.en.html.erb
和login.es.html.erb
。
这也是不正确的,因为唯一不同的路线就是上述路线。 其余的观点(约30行)将重复的所有意见。 这不会很干。
我想我可以使用“局部化的部分”,但似乎太笨重; 我想我更喜欢有这么多小视图文件的第一个选项。
所以我的问题是:有没有一个“适当”的方式来实现呢?
log_in_message_html: "This is a text, with a %{href} inside." log_in_href: "link" <p> <%= t("log_in_message_html", :href => link_to(t("log_in_href"), login_path)) %> </p>
在locale.yml文件中分离文本和链接的工作一段时间,但较长的文本很难翻译和维护,因为链接是在单独的翻译项目(如在Simones答案)。 如果你开始有很多string/翻译与链接,你可以干一点点。
我在application_helper.rb中做了一个助手:
# Converts # "string with __link__ in the middle." to # "string with #{link_to('link', link_url, link_options)} in the middle." def string_with_link(str, link_url, link_options = {}) match = str.match(/__([^_]{2,30})__/) if !match.blank? raw($` + link_to($1, link_url, link_options) + $') else raise "string_with_link: No place for __link__ given in #{str}" if Rails.env.test? nil end end
在我的en.yml中:
log_in_message: "Already signed up? __Log in!__"
在我看来:
<p><%= string_with_link(t('.log_in_message'), login_path) %></p>
通过这种方式,消息的翻译也变得更加容易,因为链接文本在locale.yml文件中也是明确定义的。
我采取了霍利斯解决scheme,并从中创build了一个gem 。 我们来看一个例子:
log_in_message: "Already signed up? %{login:Log in!}"
接着
<p><%=t_link "log_in_message", :login => login_path %></p>
有关更多详细信息,请参阅https://github.com/iGEL/it 。
holli,非常感谢你分享这个方法。 它对我来说就像一个魅力。 如果可以的话,会投你一票,但这是我的第一篇文章,所以我缺乏适当的声誉…作为一个额外的难题:我意识到你的做法的问题是,它仍然不会从里面工作控制器。 我做了一些研究,并将你的方法与格伦的方法结合在一起。
这是我想出来的:
查看助手,例如application_helper.rb
def render_flash_messages messages = flash.collect do |key, value| content_tag(:div, flash_message_with_link(key, value), :class => "flash #{key}") unless key.to_s =~ /_link$/i end messages.join.html_safe end def flash_message_with_link(key, value) link = flash["#{key}_link".to_sym] link.nil? ? value : string_with_link(value, link).html_safe end # Converts # "string with __link__ in the middle." to # "string with #{link_to('link', link_url, link_options)} in the middle." # --> see http://stackoverflow.com/questions/2543936/rails-i18n-translating-text-with-links-inside (holli) def string_with_link(str, link_url, link_options = {}) match = str.match(/__([^_]{2,30})__/) if !match.blank? $` + link_to($1, link_url, link_options) + $' else raise "string_with_link: No place for __link__ given in #{str}" if Rails.env.test? nil end end
在控制器中:
flash.now[:alert] = t("path.to.translation") flash.now[:alert_link] = here_comes_the_link_path # or _url
在locale.yml中:
path: to: translation: "string with __link__ in the middle"
在看法:
<%= render_flash_messages %>
希望这个post赢得了我的名誉投票你,holli :)任何反馈是值得欢迎的。
在en.yml
registration: terms: text: "I do agree with the terms and conditions: %{gtc} / %{stc}" gtc: "GTC" stc: "STC"
在de.yml
registration: terms: text: "Ich stimme den Geschäfts- und Nutzungsbedingungen zu: %{gtc} / %{stc}" gtc: "AGB" stc: "ANB"
在new.html.erb [假定]
<%= t( 'registration.terms.text', gtc: link_to(t('registration.terms.gtc'), terms_and_conditions_home_index_url + "?tab=gtc"), stc: link_to(t('registration.terms.stc'), terms_and_conditions_home_index_url + "?tab=stc") ).html_safe %>
我们有以下几点:
module I18nHelpers def translate key, options={}, &block s = super key, options # Default translation if block_given? String.new(ERB::Util.html_escape(s)).gsub(/%\|([^\|]*)\|/){ capture($1, &block) # Pass in what's between the markers }.html_safe else s end end alias :t :translate end
或者更明确地说:
module I18nHelpers # Allows an I18n to include the special %|something| marker. # "something" will then be passed in to the given block, which # can generate whatever HTML is needed. # # Normal and _html keys are supported. # # Multiples are ok # # mykey: "Click %|here| and %|there|" # # Nesting should work too. # def translate key, options={}, &block s = super key, options # Default translation if block_given? # Escape if not already raw HTML (html_escape won't escape if already html_safe) s = ERB::Util.html_escape(s) # ActiveSupport::SafeBuffer#gsub broken, so convert to String. # See https://github.com/rails/rails/issues/1555 s = String.new(s) # Find the %|| pattern to substitute, then replace it with the block capture s = s.gsub /%\|([^\|]*)\|/ do capture($1, &block) # Pass in what's between the markers end # Mark as html_safe going out s = s.html_safe end s end alias :t :translate end
然后在ApplicationController.rb中
class ApplicationController < ActionController::Base helper I18nHelpers
给定en.yml
文件中的一个关键字
mykey: "Click %|here|!"
可以在ERB中使用
<%= t '.mykey' do |text| %> <%= link_to text, 'http://foo.com' %> <% end %>
应该生成
Click <a href="http://foo.com">here</a>!
我想要更多的灵活性,只是添加链接到YAML文件(例如login的用户名等)的Flash消息,所以我想在string中使用ERB表示法。
正如我使用bootstrap_flash
所以我修改了助手代码,如下所示,在显示之前解码ERBstring:
require 'erb' module BootstrapFlashHelper ALERT_TYPES = [:error, :info, :success, :warning] unless const_defined?(:ALERT_TYPES) def bootstrap_flash flash_messages = [] flash.each do |type, message| # Skip empty messages, eg for devise messages set to nothing in a locale file. next if message.blank? type = type.to_sym type = :success if type == :notice type = :error if type == :alert next unless ALERT_TYPES.include?(type) Array(message).each do |msg| begin msg = ERB.new(msg).result(binding) if msg rescue Exception=>e puts e.message puts e.backtrace end text = content_tag(:div, content_tag(:button, raw("×"), :class => "close", "data-dismiss" => "alert") + msg.html_safe, :class => "alert fade in alert-#{type}") flash_messages << text if msg end end flash_messages.join("\n").html_safe end end
然后可以使用如下的string(使用devise):
signed_in: "Welcome back <%= current_user.first_name %>! <%= link_to \"Click here\", account_path %> for your account."
这可能不适用于所有情况,可能有一个说法,代码和string的定义不应混合(特别是从DRY的angular度来看),但这似乎对我很好。 代码应该适用于许多其他情况,重要的是以下几点:
require 'erb' .... begin msg = ERB.new(msg).result(binding) if msg rescue Exception=>e puts e.message puts e.backtrace end
我认为做一个简单的方法就是简单地做:
<%= link_to some_path do %> <%= t '.some_locale_key' %> <% end %>
为什么不使用第一种方式,而是像分裂一样
log_in_message: Already signed up? log_in_link_text: Log in!
接着
<p> <%= t('log_in_message') %> <%= link_to t('log_in_link_text'), login_path %> </p>