ruby-on-rails - multi - rails translation interpolation
rails i18n-traducción de texto con enlaces dentro (9)
¿Por qué no usar de la primera manera, pero dividirlo como
log_in_message: Already signed up?
log_in_link_text: Log in!
Y entonces
<p> <%= t(''log_in_message'') %> <%= link_to t(''log_in_link_text''), login_path %> </p>
Me gustaría encontrar un texto que se vea así:
¿Ya estás registrado? ¡Iniciar sesión!
Tenga en cuenta que hay un enlace en el texto. En este ejemplo, apunta a google; en realidad, apuntará a log_in_path
mi aplicación.
He encontrado dos formas de hacerlo, pero ninguno de ellos se ve "bien".
La primera forma que conozco implica tener este mi en.yml
:
log_in_message: "Already signed up? <a href=''{{url}}''>Log in!</a>"
Y en mi opinión:
<p> <%= t(''log_in_message'', :url => login_path) %> </p>
Esto funciona , pero tener la <a href=...</a>
parte en el en.yml
no me parece muy limpio.
La otra opción que conozco es usar vistas localizadas : login.en.html.erb
y login.es.html.erb
.
Esto tampoco se siente bien ya que la única línea diferente sería la mencionada; el resto de la vista (~ 30 líneas) se repetiría para todas las vistas. No sería muy seco
Creo que podría usar "parciales localizados", pero parece demasiado engorroso; Creo que prefiero la primera opción para tener tantos archivos de vista pequeños.
Entonces mi pregunta es: ¿hay una forma "adecuada" de implementar esto?
Creo que una forma simple de hacerlo es simplemente haciendo:
<%= link_to some_path do %>
<%= t ''.some_locale_key'' %>
<% end %>
En en.yml
registration:
terms:
text: "I do agree with the terms and conditions: %{gtc} / %{stc}"
gtc: "GTC"
stc: "STC"
En de.yml
registration:
terms:
text: "Ich stimme den Geschäfts- und Nutzungsbedingungen zu: %{gtc} / %{stc}"
gtc: "AGB"
stc: "ANB"
en new.html.erb [assume]
<%= 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 %>
Muchas gracias, holli, por compartir este enfoque. Funciona como un encanto para mí. Te votaría si pudiera, pero esta es mi primera publicación, así que me falta la reputación adecuada ... Como una pieza adicional al rompecabezas: el problema que me di cuenta con tu enfoque es que todavía no funcionará desde adentro el controlador. Investigué un poco y combiné tu enfoque con el de Glenn en rubypond .
Aquí es lo que se me ocurrió:
Ver ayudante, por ejemplo, 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://.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
En el controlador:
flash.now[:alert] = t("path.to.translation")
flash.now[:alert_link] = here_comes_the_link_path # or _url
En el locale.yml:
path:
to:
translation: "string with __link__ in the middle"
En la vista:
<%= render_flash_messages %>
Espero que este post me gane la reputación de votarte, holli :) Cualquier comentario es bienvenido.
Quería un poco más de flexibilidad que simplemente agregar enlaces a mensajes flash de archivos YAML (por ejemplo, el nombre de usuario registrado, etc.), así que en su lugar quería usar la notación ERB en la cadena.
Como estoy usando bootstrap_flash
, modifiqué el código auxiliar de la siguiente manera para decodificar las cadenas ERB antes de mostrar:
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
Entonces es posible usar cadenas como las siguientes (usando el dispositivo):
signed_in: "Welcome back <%= current_user.first_name %>! <%= link_to /"Click here/", account_path %> for your account."
Esto puede no funcionar para todas las situaciones y puede haber un argumento de que las definiciones de código y cadena no deben mezclarse (especialmente desde la perspectiva DRY), pero esto parece funcionar bien para mí. El código debe ser adaptable para muchas otras situaciones, los bits importantes son los siguientes:
require ''erb''
....
begin
msg = ERB.new(msg).result(binding) if msg
rescue Exception=>e
puts e.message
puts e.backtrace
end
Separar el texto y el enlace en el archivo locale.yml funciona por un tiempo, pero con el texto más largo es difícil de traducir y mantener ya que el enlace está en un elemento de traducción separado (como en la respuesta de Simones). Si comienza a tener muchas cadenas / traducciones con enlaces, puede secarlo un poco más.
Hice una ayuda en mi 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 mi en.yml:
log_in_message: "Already signed up? __Log in!__"
Y en mi opinión:
<p><%= string_with_link(t(''.log_in_message''), login_path) %></p>
De esta forma, es más fácil traducir mensajes, ya que también el texto del enlace está claramente definido en los archivos locale.yml.
Tomé la solución hollis e hice github.com/iGEL/it sacó. Veamos un ejemplo:
log_in_message: "Already signed up? %{login:Log in!}"
Y entonces
<p><%=t_link "log_in_message", :login => login_path %></p>
Para obtener más detalles, consulte github.com/iGEL/it .
Tuvimos lo siguiente:
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
o más explícitamente:
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
luego en ApplicationController.rb solo
class ApplicationController < ActionController::Base
helper I18nHelpers
Dada una clave en el archivo en.yml
como
mykey: "Click %|here|!"
se puede usar en ERB como
<%= t ''.mykey'' do |text| %>
<%= link_to text, ''http://foo.com'' %>
<% end %>
debería generar
Click <a href="http://foo.com">here</a>!
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>