ruby-on-rails - tutorial - rails i18n models
Rails enlazan a la página actual y le pasan parámetros. (5)
Estoy agregando I18N a mi aplicación de rieles al pasar la configuración regional utilizando url params. Mis direcciones URL son similares a http://example.com/en/users y http://example.com/ar/users (para las configuraciones regionales en inglés y árabe, respectivamente).
En mi archivo de rutas, he definido mis rutas con una opción: path_prefix:
map.resources :users, :path_prefix => ''/:locale''
Y la configuración regional se establece utilizando un before_filter definido en ApplicationController
def set_locale
I18n.locale = params[:locale]
end
También definí ApplicationController # default_url_options, para agregar la configuración regional a todas las direcciones URL generadas por la aplicación:
def default_url_options(options={})
{:locale => I18n.locale}
end
Lo que quiero es agregar un enlace en el encabezado del diseño (que se muestra en todas las páginas) que se vincularía a la misma página pero con la otra configuración regional.
Por ejemplo, si estoy navegando en la configuración regional árabe, quiero un enlace "Inglés" en el encabezado, que me redireccionará a mi página actual y establecerá la configuración regional en inglés. ¿Hay una manera de hacer esto en los carriles?
Así que encontré una manera de hacer esto más explícitamente sin depender de (tanto) la magia de los rieles.
url_for(params.merge({:your_new_parameter => value}))
Esto debería funcionar en cualquier link_to
.
Todo lo que hace es tomar los parámetros de la solicitud actual y fusionar el nuevo hash deseado en ellos y luego crear una nueva URL para eso.
Eche un vistazo a esto, aunque puede que no sea SECO y correcto, pero funciona perfectamente para mí. Lee todos los parámetros que proporcionó, reemplazando solo las direcciones URL de la configuración regional EX: http://example.com:3000/us/users?t=123&m=343 etc.
def us_link
link_to "US", form_locale_url("/us")
end
def jp_link
link_to "Japan",form_locale_url("/jp")
end
def form_locale_url(locale)
new_url = request.request_uri
new_locale_url = new_us_url = new_jp_url = new_url
if new_url == "/"
new_locale_url.sub!(////,locale)
elsif (new_url =~///us/) == 0
new_us_url.sub!(///us/,locale)
elsif (new_url =~///jp/) == 0
new_jp_url.sub!(///jp/,locale)
end
end
Me tomó un tiempo encontrar esto, pero aquí está mi solución:
link_to ''English'', url_for( :locale => ''en'' )
link_to ''Deutch'', url_for( :locale => ''de'' )
De los documentos aquí: http://api.rubyonrails.org/classes/ActionController/Base.html#M000649
Al generar una nueva URL, los valores faltantes se pueden completar a partir de los parámetros de la solicitud actual. Por ejemplo, url_for: action => ''some_action'' conservará el controlador actual, como se esperaba. Este comportamiento se extiende a otros parámetros, incluyendo: controller,: id, y cualquier otro parámetro que se coloque en la ruta de una ruta.
Por lo tanto, utilizar url_for se establecerá de forma predeterminada en los parámetros de la solicitud actual, solo cambie el que desee en su código. En este caso, todo lo que cambié fue: locale, por lo que todo lo demás permanece igual.
Tenga en cuenta que esto también funciona para "oculto": parámetros. Así que si tienes:
map.my_map '':locale/my_map'', :controller => ''home'', :action => ''my_map''
el uso de la url_for anterior en la página / es / my_map no tendrá ''home'' en la url (es decir, / en / home / my_map). Prima.
Puede analizar request_uri y reemplazar su configuración regional en la ruta con expresión regular
Ok, aquí hay un ejemplo de ayuda. Si entiendo correctamente el objetivo.
def locale_url(url, locale)
url.gsub(////w*$/, "/#{locale}")
end
url = "http://www.domain.com/products/1/ru" # or request.request_uri
locale = "en"
locale_url(url, locale) #=> "http://www.domain.com/products/1/en"
Este es un punto de inicio, por lo que puede hacer algunas cosas diferentes que necesita
Enlace a la página actual con diferentes locales
Probado en rieles 4
Hola a todos. Después de un tiempo de investigación, decido escribir mi propia solución para esto.
link_to ''English'', url_for( :locale => ''en'' )
link_to ''Deutch'', url_for( :locale => ''de'' )
Esto funciona a la perfección, pero permite que la vulnerabilidad XSS simplemente pase parámetros en su URL como se muestra a continuación:
http://localhost:3000/en/about?host=www.fishingsiteorbadurl.com/%23&port=80
O en el peor de los casos:
http://localhost:3000/en/about?host=%D0%BE%D1%87%D0%B5%D0%BD%D1%8C%D0%BF%D0%BB%D0%BE%D1%85%D0%BE%D0%B9%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84
Compruebe qué URL obtendrá después de leer este enlace en su aplicación.
Mi solución de producción. El método "cambiar el idioma" redirige a cualquier página con la configuración regional adecuada usando HTTP_REFERER en el objeto de solicitud. Tenga en cuenta: el método URI.path para obtener solo la ruta, no la URL completa
Realiza el método de "cambio de idioma" en cualquier controlador:
def change_lang
if request.referer.nil?
refer = root_url
else
uri = URI(request.referer)
refer = uri.path
end
lang = params[:lang]
cookies[:locale] = lang
redirect_to refer
end
application_controller.rb
before_action :set_locale
def set_locale
# -- Get lang from cookies or url parameter locale
user_locale = cookies[:locale] || params[:locale]
# -- If present
if user_locale.present?
# -- If it is has 2 symbols
user_locale = user_locale.scan(/[a-zA-Z]{2}/)
else
# -- If no - use default en locale
user_locale = ''en''
end
# -- Check, is this locale available for using.
# Please note: this needed for disable invalid locale warning.
if I18n.available_locales.include?(user_locale[0].to_sym)
I18n.locale = user_locale[0]
else
I18n.locale = "en"
end
end
agrega esto a tu diseño
<%= link_to ''English'', change_lang_path(''en'') %> <%= link_to ''Russian'', change_lang_path(''ru'') %>
config / route.rb
scope "(:locale)", locale: /[a-zA-Z]{2}/ do
get "change_lang/:lang" => "users#change_lang", :as => "change_lang"
end
No es necesario utilizar params.merge o cualquier solución de parche de mono.
Espero que esto ayude, porque personalmente dediqué mucho tiempo a resolverlo.