Skip to content

How To: OmniAuth inside localized scope

Keita Tsukamoto edited this page Dec 10, 2018 · 7 revisions

gurix provided the following solution in response to issue #272

First we need a controller inside the locale scope that sets us the current locale in the session. routes.rb:

Rails.application.routes.draw do
  # We need to define devise_for just omniauth_callbacks:auth_callbacks otherwise it does not work with scoped locales
  # see https://github.com/plataformatec/devise/issues/2813
  devise_for :users, only: :omniauth_callbacks, controllers: { omniauth_callbacks: 'omniauth_callbacks' }

  scope '(:locale)' do
    # We define here a route inside the locale thats just saves the current locale in the session
    get 'omniauth/:provider' => 'omniauth#localized', as: :localized_omniauth

    devise_for :users, skip: :omniauth_callbacks, controllers: { passwords: 'passwords', registrations: 'registrations', omniauth_callbacks: 'omniauth_callbacks' }
  end
end

omniauth_controller.rb:

class OmniauthController < ApplicationController
  def localized
    # Just save the current locale in the session and redirect to the unscoped path as before
    session[:omniauth_login_locale] = I18n.locale
    omniauth_authorize_path = if params[:provider] == 'twitter'
                                user_twitter_omniauth_authorize_path
                              elsif params[:provider] == 'facebook'
                                user_facebook_omniauth_authorize_path
                              else
                                new_user_session_path
                              end
    redirect_to omniauth_authorize_path
  end
end

Now we can force the locale inside the omniauth_callbacks_controller.rb:

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def twitter
    handle_redirect('devise.twitter_uid', 'Twitter')
  end

  def facebook
    handle_redirect('devise.facebook_data', 'Facebook')
  end

  private

  def handle_redirect(_session_variable, kind)
    # Use the session locale set earlier; use the default if it isn't available.
    I18n.locale = session[:omniauth_login_locale] || I18n.default_locale
    sign_in_and_redirect user, event: :authentication
    set_flash_message(:notice, :success, kind: kind) if is_navigational_format?
  end

  def user
    User.find_for_oauth(env['omniauth.auth'], current_user)
  end
end

That's all, every time you login via link_to t('.sign_up_with_twitter'), localized_omniauth_path(:twitter), or whatever, it forces the intended locale.

Also as gist https://gist.github.com/gurix/4ed589b5551661c1536a

Clone this wiki locally