i18n Routing To Mounted Engine - Ignoring locale

后端 未结 1 671
情话喂你
情话喂你 2020-12-17 00:10

I have an application (my_test_app) with working i18n support built. Currently, there are two language files available, FR & EN, and if I toggle back and forth between

相关标签:
1条回答
  • 2020-12-17 00:29

    I am using Engine with I18n and it works fine. I created a dummy Rails application to try your scenario. As far as I know, changing the locale inside the URL works fine with routes defined in your Rails application:

    My routes:

    Bar::Application.routes.draw do
      root 'posts#index'
    
      scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
        resources :posts, only: :index
      end
    end
    

    I am able to change the I18n locale with:

    http://localhost:3000/fr/posts
    http://localhost:3000/en/posts
    

    I think that your probleme is when you want to go to any of your engine's routes since you did not set the I18n locale switch. See bellow:

    engine_jobs GET    /engine_jobs(.:format)
    

    Then, when going to /engine_jobs even if you specified a locale in the URL, it's I18n default locale that will be set (en):

    def set_locale
      I18n.locale = params[:locale] || I18n.default_locale
      # ...
    end
    

    When using your Engine routes, params[:locale] is nil

    Solution

    Add the same logic to your engine's routes:

    config/routes.rb

    MyTestApp::Application.routes.draw do
    
      mount MyEngine::Engine, at: "/my_engine"
    
      match '*path', to: redirect("/#{I18n.default_locale}/%{path}"), constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" and !req.path == "/#{I18n.default_locale}/"}
      match '', to: redirect("/#{I18n.default_locale}/")
    end
    

    your_engine/config/routes.rb

    MyEngine::Engine.routes.draw do
      scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
        resources :my_jobs
      end
    end
    

    mount MyEngine::Engine, at: "/my_engine" only tells rails to "load" all engine routes. If you need to add constraints, scopes, namespace or anything else, you should use usual rails way to do it but in your engine's routes file.

    Finally you need to update both of your application_controller.rb (main app + engine) with the following:

    class ApplicationController < ActionController::Base
      def url_options
        { locale: I18n.locale }
      end
    
      def set_locale
        I18n.locale = params[:locale] || I18n.default_locale
        Rails.application.routes.default_url_options[:locale]= I18n.locale
      end
    end
    
    0 讨论(0)
提交回复
热议问题