Skip to content

Instantly share code, notes, and snippets.

@frahugo
Last active July 14, 2022 17:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frahugo/705b0854126eb3ae7565 to your computer and use it in GitHub Desktop.
Save frahugo/705b0854126eb3ae7565 to your computer and use it in GitHub Desktop.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :set_locale
protect_from_forgery
protected
def set_locale
# RouteTranslator already assigned a locale to I18n.locale
# Include here some logic to tweak it
# .
# .
# .
# Save in request env so middlewares can use it.
request.env['app.current_locale'] = I18n.locale.to_s
end
end
# config/initializers/devise.rb
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
#
config.warden do |manager|
manager.failure_app = Devise::TranslatedFailureApp
end
end

RouteTranslator gem is wrapping the current locale assignment in an around_filter set_locale_from_url and then resets it to the previous value.

Devise has a FailureApp to deal with unauthenticated requests, and it uses I18n to build the flash message and the redirection URL. But at that stage, the I18n default locale is set and the messages and URL are not localized in the context of the request (i.e. if the request URL is in French, and the default locale of the app is English, Devise will redirect to the English URL with an english flash message).

This is a solution for propagating the application locale to the the Devise middleware.

# lib/devise/translated_failure_app.rb
module Devise
# Failure application that will be called every time :warden is thrown from
# any strategy or hook. Responsible for redirect the user to the sign in
# page based on current scope and mapping. If no scope is given, redirect
# to the default_url.
class TranslatedFailureApp < Devise::FailureApp
def route(scope)
if locale_supplied_by_app?
"new_#{scope}_session_#{app_locale}_url"
else
super(scope)
end
end
protected
def i18n_options(options)
hash = super(options)
if locale_supplied_by_app?
hash.merge(locale: app_locale)
else
hash
end
end
def locale_supplied_by_app?
app_locale.present?
end
def app_locale
@app_locale ||= env['app.current_locale']
end
end
end
@OleksandrPoltavets
Copy link

Thanks for the gist!
It looks like mistake in this line: https://gist.github.com/frahugo/705b0854126eb3ae7565#file-translated_failure_app-rb-L34
I guess it should be request.env['app.current_locale']

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