Following is example of what I think its good practice on setting up I18n on pages, this mini pattern can later grow but I think it is a good starting point.
Let's say you have BaseController which will be extended by your controllers.
class BaseController < ActionController::Base
before_filter :set_session_locale
def set_session_locale
session[:selected_locale] = params[:lang].nil? ? session[:selected_locale] : params[:lang]
I18n.locale = session[:selected_locale] || I18n.default_locale
end
end
before_filter will make sure that this is triggered before each request, this is important since I18n will not persist beyond one request. Priority will be given to URL param lang, if not than to session locale, if not than to default locale.
Session will be used to propagate locale selected. You can force language with each request to each controller than extends BaseController for example:
localhost:3000/index?lang=de
To extend this approach for registered users you can use another controller which will be used once user is logged in. Here is example of this ApplicationController
class ApplicationController < BaseController
before_filter :set_user_locale
skip_before_filter :set_session_locale
# Application code which will among other things set @user
def set_user_locale
I18n.locale = @user.locale|| I18n.default_locale
end
end
We can see now that before_filter is used to trigger user preferred locale, if none is present it default to I18n one.
I18n.locale = @user.locale|| I18n.default_locale
We can see that skip_before_filter is used to disable BaseController's set session
locale, since priority is now to user. If we didn't added this filter this would still work fine,
but there would be unnecessary call to set_session_locale method, from
ApplicationController.
Have fun and tweak approach to your needs. If you have any questions leave it at comments section I will be happy to answer them.