我想要一个看起来像这样的文本:
已经注册? Log in!
请注意,文字上有一个链接。在这个例子中它指向谷歌 - 实际上它将指向我的应用程序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>
上使用en.yml
部分对我来说并不是很干净。
我知道的另一个选项是使用localized views - login.en.html.erb
和login.es.html.erb
。
这也感觉不对,因为唯一不同的路线就是前面提到的那条;对于所有视图,将重复视图的其余部分(~30行)。它不会很干。
我想我可以使用“局部部分”,但这似乎太麻烦了;我想我更喜欢有这么多小视图文件的第一个选项。
所以我的问题是:有没有“正确”的方法来实现这个?
答案 0 :(得分:170)
<强> en.yml 强>
log_in_message_html: "This is a text, with a %{href} inside."
log_in_href: "link"
<强> login.html.erb 强>
<p> <%= t("log_in_message_html", href: link_to(t("log_in_href"), login_path)) %> </p>
答案 1 :(得分:11)
将locale.yml文件中的文本和链接分开工作一段时间但文本较长,因为链接位于单独的翻译项目中(如Simones的答案),难以翻译和维护。如果您开始使用链接开始使用许多字符串/翻译,您可以稍微干一点。
我在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文件中明确定义。
答案 2 :(得分:7)
我采用了hollis解决方案,并将a gem called it
从中取出。我们来看一个例子:
log_in_message: "Already signed up? %{login:Log in!}"
然后
<p><%=t_link "log_in_message", :login => login_path %></p>
有关详细信息,请参阅https://github.com/iGEL/it。
答案 3 :(得分:5)
在 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 %>
答案 4 :(得分:3)
非常感谢,holli,分享这种方法。它对我来说就像一个魅力。如果可以,我会投票给你,但这是我的第一篇文章,所以我缺乏正确的声誉......作为一个额外的难题:我用你的方法意识到的问题是它仍然无法从里面工作控制器。我做了一些研究,并将您的方法与Glenn on rubypond中的方法结合起来。
以下是我提出的建议:
查看助手,例如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 %>
希望这篇文章赢得了投票给你的声誉,holli :) 欢迎任何反馈。
答案 5 :(得分:2)
我们有以下内容:
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>!
答案 6 :(得分:1)
我希望比仅添加来自YAML文件的Flash消息的链接(例如登录的用户名等)更灵活,所以我想在字符串中使用ERB表示法。
当我使用bootstrap_flash
时,我按如下方式修改了助手代码,以便在显示之前解码ERB字符串:
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, e.g. 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
然后可以使用如下的字符串(使用设计):
signed_in: "Welcome back <%= current_user.first_name %>! <%= link_to \"Click here\", account_path %> for your account."
这可能不适用于所有情况,并且可能存在不应混合代码和字符串定义的论点(特别是从DRY的角度来看),但这对我来说似乎很有效。代码应该适用于许多其他情况,重要的部分如下:
require 'erb'
....
begin
msg = ERB.new(msg).result(binding) if msg
rescue Exception=>e
puts e.message
puts e.backtrace
end
答案 7 :(得分:-1)
我认为这样做的一个简单方法就是:
<%= link_to some_path do %>
<%= t '.some_locale_key' %>
<% end %>
答案 8 :(得分:-4)
为什么不使用第一种方式,而是将其拆分为
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>