i18n路由到已安装的引擎 - 忽略区域设置

Mic*_*V69 7 rails-routing rails-engines ruby-on-rails-3.2 rails-i18n

我有一个应用程序(my_test_app),内置了i18n支持.目前,有两种语言文件可用,FR&EN,如果我在它们之间来回切换,一切正常,因为我希望看到非引擎功能,如用户索引/显示/编辑/删除(ISED)选项.

在my_test_app中,我安装了一个Rails引擎(my_engine),它有一个控制器和模型集(engine_job).所以,一个可行的URL应该是

http://0.0.0.0:3000/fr/my_engine/engine_job
Run Code Online (Sandbox Code Playgroud)

然而,无论我选择何种语言,它总是出现在EN中.检查参数显示:

--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
locale: fr
action: index
controller: my_engine/engine_job
Run Code Online (Sandbox Code Playgroud)

然而,所选择的翻译是EN.

my_test_app route.rb:

MyTestApp::Application.routes.draw do

  scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
    mount MyEngine::Engine, at: "/my_engine"
  end # scope locale

  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
Run Code Online (Sandbox Code Playgroud)

my_engine route.rb:

MyEngine::Engine.routes.draw do
  resources :my_jobs
end
Run Code Online (Sandbox Code Playgroud)

耙路线:

my_engine        (/:locale)/my_engine           MyEngine::Engine {:locale=>/en|fr/}
                             /*path(.:format)                    :controller#:action
                             /                                   :controller#:action
                users GET    (/:locale)/users(.:format)          users#index {:locale=>/en|fr/}
                      POST   (/:locale)/users(.:format)          users#create {:locale=>/en|fr/}
             new_user GET    (/:locale)/users/new(.:format)      users#new {:locale=>/en|fr/}
            edit_user GET    (/:locale)/users/:id/edit(.:format) users#edit {:locale=>/en|fr/}
                 user GET    (/:locale)/users/:id(.:format)      users#show {:locale=>/en|fr/}
                      PUT    (/:locale)/users/:id(.:format)      users#update {:locale=>/en|fr/}
                      DELETE (/:locale)/users/:id(.:format)      users#destroy {:locale=>/en|fr/}
             sessions POST   (/:locale)/sessions(.:format)       sessions#create {:locale=>/en|fr/}
          new_session GET    (/:locale)/sessions/new(.:format)   sessions#new {:locale=>/en|fr/}
              session DELETE (/:locale)/sessions/:id(.:format)   sessions#destroy {:locale=>/en|fr/}
               signup        (/:locale)/signup(.:format)         users#new {:locale=>/en|fr/}
               signin        (/:locale)/signin(.:format)         sessions#new {:locale=>/en|fr/}
              signout DELETE (/:locale)/signout(.:format)        sessions#destroy {:locale=>/en|fr/}
                 help        (/:locale)/help(.:format)           static_pages#help {:locale=>/en|fr/}
                about        (/:locale)/about(.:format)          static_pages#about {:locale=>/en|fr/}
                 root        /(:locale)(.:format)                static_pages#home {:locale=>/en|fr/}

Routes for MyEngine::Engine {:locale=>/en|fr/}:
    engine_jobs GET    /engine_jobs(.:format)          my_engine/engine_jobs#index
                POST   /engine_jobs(.:format)          my_engine/engine_jobs#create
 new_engine_job GET    /engine_jobs/new(.:format)      my_engine/engine_jobs#new
edit_engine_job GET    /engine_jobs/:id/edit(.:format) my_engine/engine_jobs#edit
     engine_job GET    /engine_jobs/:id(.:format)      my_engine/engine_jobs#show
                PUT    /engine_jobs/:id(.:format)      my_engine/engine_jobs#update
                DELETE /engine_jobs/:id(.:format)      my_engine/engine_jobs#destroy
Run Code Online (Sandbox Code Playgroud)

此外,在引擎中单击的任何链接都将语言设置为EN.一些网络搜索没有明确说明这里可能发生的事情,因为我能找到的所有i18n示例都不涉及已安装的引擎.

编辑:显示设置默认语言环境的代码my_test_app/app/controllers/application_controller.rb:

class ApplicationController < ActionController::Base
  protect_from_forgery
  helper MyEngine::Engine.helpers

  ActiveRecord::Base.verify_active_connections!

  before_filter :set_locale

  private
    def set_locale
      I18n.locale = params[:locale] || I18n.default_locale
      Rails.application.routes.default_url_options[:locale]= I18n.locale
      logger.debug "My_Test_App:  default_url_options is passed options: #{Rails.application.routes.default_url_options.inspect}\n"
      # current_user.locale
      # request.subdomain
      # request.env["HTTP_ACCEPT_LANGUAGE"]
      # request.remote_ip
    end # set_locale

end # class ApplicationController
Run Code Online (Sandbox Code Playgroud)

/编辑

EDIT2(Pierre 8月9日15:59建议更改后的路线图):

申请路线http://0.0.0.0:3000/en/users"locale"=>"en".帮助者创建的引擎路线看起来像http://0.0.0.0:3000/my_engine?locale=en/engine_jobs和yeilds No route matches [GET] "/my_engine".

my_engine_plugin        /my_engine                     MyEnginePlugin::Engine
                users GET    (/:locale)/users(.:format)          users#index {:locale=>/en|fr/}
                      POST   (/:locale)/users(.:format)          users#create {:locale=>/en|fr/}
             new_user GET    (/:locale)/users/new(.:format)      users#new {:locale=>/en|fr/}
            edit_user GET    (/:locale)/users/:id/edit(.:format) users#edit {:locale=>/en|fr/}
                 user GET    (/:locale)/users/:id(.:format)      users#show {:locale=>/en|fr/}
                      PUT    (/:locale)/users/:id(.:format)      users#update {:locale=>/en|fr/}
                      DELETE (/:locale)/users/:id(.:format)      users#destroy {:locale=>/en|fr/}
             sessions POST   (/:locale)/sessions(.:format)       sessions#create {:locale=>/en|fr/}
          new_session GET    (/:locale)/sessions/new(.:format)   sessions#new {:locale=>/en|fr/}
              session DELETE (/:locale)/sessions/:id(.:format)   sessions#destroy {:locale=>/en|fr/}
               signup        (/:locale)/signup(.:format)         users#new {:locale=>/en|fr/}
               signin        (/:locale)/signin(.:format)         sessions#new {:locale=>/en|fr/}
              signout DELETE (/:locale)/signout(.:format)        sessions#destroy {:locale=>/en|fr/}
                 help        (/:locale)/help(.:format)           static_pages#help {:locale=>/en|fr/}
                about        (/:locale)/about(.:format)          static_pages#about {:locale=>/en|fr/}
                 root        /(:locale)(.:format)                static_pages#home {:locale=>/en|fr/}

Routes for MyEnginePlugin::Engine:
    engine_jobs GET    (/:locale)/engine_jobs(.:format)          my_engine_plugin/engine_jobs#index {:locale=>/en|fr/}
                     POST   (/:locale)/engine_jobs(.:format)          my_engine_plugin/engine_jobs#create {:locale=>/en|fr/}
 new_engine_job GET    (/:locale)/engine_jobs/new(.:format)      my_engine_plugin/engine_jobs#new {:locale=>/en|fr/}
edit_engine_job GET    (/:locale)/engine_jobs/:id/edit(.:format) my_engine_plugin/engine_jobs#edit {:locale=>/en|fr/}
     engine_job GET    (/:locale)/engine_jobs/:id(.:format)      my_engine_plugin/engine_jobs#show {:locale=>/en|fr/}
                     PUT    (/:locale)/engine_jobs/:id(.:format)      my_engine_plugin/engine_jobs#update {:locale=>/en|fr/}
                     DELETE (/:locale)/engine_jobs/:id(.:format)      my_engine_plugin/engine_jobs#destroy {:locale=>/en|fr/}
Run Code Online (Sandbox Code Playgroud)

/ EDIT2(Pierre 8月9日15:59建议更改后的路线图)

所以,问题是我需要对我的路线或引擎进行哪些更改才能使其按预期工作?

提前感谢您的时间和建议!

Pie*_*ois 4

我正在使用带有 I18n 的引擎,它工作得很好。我创建了一个虚拟 Rails 应用程序来尝试您的场景。据我所知,更改 URL 内的区域设置可以与 Rails 应用程序中定义的路由配合使用:

我的路线:

Bar::Application.routes.draw do
  root 'posts#index'

  scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
    resources :posts, only: :index
  end
end
Run Code Online (Sandbox Code Playgroud)

我可以使用以下命令更改 I18n 语言环境:

http://localhost:3000/fr/posts
http://localhost:3000/en/posts
Run Code Online (Sandbox Code Playgroud)

我认为您的问题是当您想要转到任何引擎的路线时,因为您没有设置 I18n 区域设置开关。见下图:

engine_jobs GET    /engine_jobs(.:format)
Run Code Online (Sandbox Code Playgroud)

然后,即使/engine_jobs您在 URL 中指定了语言环境,也会设置 I18n 默认语言环境 ( en):

def set_locale
  I18n.locale = params[:locale] || I18n.default_locale
  # ...
end
Run Code Online (Sandbox Code Playgroud)

当使用你的引擎路线时,params[:locale]nil

解决方案

将相同的逻辑添加到引擎的路线中:

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
Run Code Online (Sandbox Code Playgroud)

your_engine/config/routes.rb

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

mount MyEngine::Engine, at: "/my_engine"只告诉 Rails“加载”所有引擎路线。如果您需要添加约束、范围、命名空间或其他任何内容,您应该使用通常的 Rails 方式来执行此操作,但在引擎的路由文件中。

最后,您需要application_controller.rb使用以下内容更新您的(主应用程序+引擎):

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
Run Code Online (Sandbox Code Playgroud)

  • 是的,我认为 Rails 无法找到路由,因为它希望区域设置不是作为参数,而是在 url 内...尝试将此代码添加到 `application_controller.rb` 中的 `set_locale` 方法中: routes.default_url_options[:locale] = I18n.locale`。然后在控制器中定义一个“url_options”方法。有关更多详细信息,请参阅此处 http://stackoverflow.com/questions/14875404/rails-mountable-engine-under-a-dynamic-scope#comment26855682_14875404 和此处 http://stackoverflow.com/questions/17207104/setting-default-安装导轨引擎的网址选项/18299975#18299975 (2认同)