Skip to content

Instantly share code, notes, and snippets.

@andresgutgon
Created August 18, 2010 18:31
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save andresgutgon/535725 to your computer and use it in GitHub Desktop.
Save andresgutgon/535725 to your computer and use it in GitHub Desktop.
Desplegar los idiomas que estan disponibles en tu App y setear el valor para cada usuario
#Selector de idioma
#dependencias:
# 1 - Rack locale del paquete Rack-contrib [1]
# USO: Se usa para detectar el idioma definido por el usuario en su browser ['HTTP_ACCEPT_LANGUAGE']
# Esplicado aquí http://guides.rubyonrails.org/i18n.html#using-accept-language
# [1] http://github.com/rack/rack-contrib
# 2 - Routing-filter [1]
# USO: Establecer el locale en las URLs ej.: www.mysite.com/es/foo/bar
# NOTA: Si tambien quieres traducir las URL's usa la gema de Raul Murciano Translate_routes [2] (De momento sin cobertura para Rails3)
# NOTA2: Este plugin esta orientado a Rails 3, pero la version <= 0.0.2 es compatible con Rails 2.3.x
# Descargar script/plugin install git://github.com/svenfuchs/routing-filter.git --revision 'refs/tags/v0.0.2'
# [1] http://github.com/svenfuchs/routing-filter
# [2] http://github.com/raul/translate_routes
# Una vez que tetemos las dependencias a mano, las colocamos donde toca:
# 1 Rack locale:
#ARCHIVO => enviroment.rb
require 'rack/contrib'
Rails::Initializer.run do |config|
# middlewares extras
config.middleware.use 'Rack::Locale'
# 2 Routing-filter
#ARCHIVO => routes.rb
# A partir de ahora todas las rutas generadas por los helpers de Rails llevaran el locale de serie :O
map.filter :locale
# 3 En la vista (en la que tu quieras que se vea el selector)
# En mi caso es una sencilla lista de idiomas. No muestro el actual
<ul>
<% I18n.available_locales.each do |locale| %>
<% unless locale == I18n.locale %>
<li><%= link_to I18n.t("meta.language_name", :locale => locale.to_sym), change_locale_path(:new_locale => locale) %></li>
<% end %>
<% end %>
</ul>
# Ok, ahora sólo queda por hacer dos cosas
# a) Setear el locale
# b) Recoger el locale
# a) Recoger el locale
# NOTA: Este metodo puede ir en cualquier controlador, pero como me recomendo Fernado Blat tiene sentido que valla en sessions_controller
# user_sessions_controller.rb
def set_user_language
if params[:new_locale]
locale = params[:new_locale]
# Creamos una cookie con el locale elegido por el usuario (para los no reistrados)
cookies[:current_locale] = {:value => locale, :expires => 1.year.from_now}
if logged_in?
# Si el usuario esta registrados almacenamos su locale en la BBDD
current_user.profile.language = locale
current_user.save
end
end
# NOTA: Aquí podríamos hacer un redirec_to :back que te devuelve a la acción anterior.
# Pero si la accion anterior es POST, PUT o DELETE. EL redirect_to fallara
# SOLUCION (Made in Fernando Blat) Comprobar si la accion es GET y si lo es almacenarla en session ¿cómo? **
redirect_to session[:last_get_url]
end
# b) Recoger el locale
# ARCHIVO => application_controller.rb
before_filter :get_user_language
# ...
private
def get_user_language
if logged_in?
# Si esta logado cogemos el locale de la BBDD
I18n.locale = current_user.profile.language.to_sym unless current_user.profile.language.blank?
elsif cookies[:current_locale]
# Si no esta logado pero existe la cookie la usamos
I18n.locale = cookies[:current_locale].to_sym
elsif I18n.available_locales.include?(request.env['rack.locale'].to_sym)
# Esta variable (request.env['rack.locale']) la tenemos gracias a Rack::locale
# Si no esta logado y no habia nunca cambiado de idioma cogemos el idioma que tenga en su navegador si lo tenemos
I18n.locale = request.env['rack.locale'].to_sym
else
# Si el idioma de su navegador no es uno de los que nuestra App dispone, le ponemos el idioma por defecto
I18n.locale = I18n.default_locale
end
end
# --------------------------------------------------------------------------------------------------------------
# ** Return to POST actions
# No se puede volver a acciones POST, por eso almacenamos en sesion la accion anterior a la que fue POST.
# Seteamos esta cookie de session para recoger la ultima URL que fue GET para devolver al usuario
# En caso de que se le ocurra pulsar el cambio de idioma cuando su ultima accion fue por POST, PUT o DELETE
# ARCHIVO => application_controller.rb
after_filter :last_get_url
def last_get_url
if request.method == :get
session[:last_get_url] = request.request_uri
end
end
@andresgutgon
Copy link
Author

Como curiosidad, la forma en la que se traducen los idiomas en la vista:
Ejemplo castellano:

locale/es.yml

es:
meta:
language_name: "Castellano"

view.html.erb

<%= link_to I18n.t("meta.language_name", :locale => locale.to_sym), url %>

Si os fijais locale es una variable que I18n ya conoce. Realmente no la interpola, sino que la usa para ver en que archivo locale busca la traducción.
Me parece genial!

@pmarinr
Copy link

pmarinr commented Aug 26, 2010

Gracias!!

@andresgutgon
Copy link
Author

De nada, me alegro de que te haya servido :)

@kristianmandrup
Copy link

Great stuff!!! Could someone please translate the main points of the comments in this gist to english :) Thanks!

@kristianmandrup
Copy link

Also, could someone please help port this example to Rails 3 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment