使用英语语言环境时出现奇怪的 path_helper 错误

Weird path_helper error when using english locale

我遇到了一个奇怪的错误,我不想再解决这个问题,但我明白了。

最近添加我们主页的英文版本时,我发现我无法像为德语语言环境那样生成路径:

2.3.0 :023 > I18n.available_locales
=> [:de, :en]

2.3.0 :019 > apps_path(locale: :de)
=> "/de/apps"

2.3.0 :020 > apps_path(locale: :en)
ActionController::UrlGenerationError: No route matches 
{:action=>"apps", :controller=>"pages", :locale=>:en} missing required keys: [:locale]

正如我所说,我可以通过使用 url_for 或 – 当坚持我们的示例 apps_en_path 时解决这个问题。

但我想知道是什么导致了这个奇怪的问题。

编辑

A git bisect session 帮助我发现自从我将 route-translater gem 添加到我的项目后就会发生这种情况。除了这个问题,它对我们来说工作正常。

我有这个设置(在 development.rb):

# RouteTranslator.config
config.force_locale = true
config.locale_param_key = :locale

我的routes.rb:

require_relative "#{Rails.root}/app/route_constraints/can_access_devops"

Rails.application.routes.draw do
  get 'health', to: 'health#show'

  # Redirect requests with trailing 'null'
  get '/*path/null', to: redirect('/%{path}')

  namespace :admin do
    root to: redirect('/admin/magazine_articles')

    resources :jobs
    resources :users
    resources :magazine_categories
    resources :magazine_articles
    resources :media_assets
    resources :advertisements do
      member do
        get 'preview'
      end
    end

    namespace :devops do
      authenticate :user do
        constraints CanAccessDevOps do
          mount PgHero::Engine, at: '/pghero'
        end
      end
    end
  end

  scope '/:locale', locale: /#{I18n.available_locales.join("|")}/ do
    root to: 'pages#home'

    localized do
      devise_for :users, controllers: { sessions: 'sessions' }

      # redirect terms of use to cockpit; this is required because
      # the packaging has a link that should point to cockpit
      get 'home',        to: 'pages#home'
      get 'imprint',     to: 'pages#imprint', as: 'imprint'
      get 'lottery',     to: 'pages#lottery', as: 'lottery'
      get 'privacy',     to: 'pages#privacy', as: 'privacy'
      get 'terms',       to: 'pages#terms',   as: 'terms'
      get 'faq',         to: 'pages#faq',     as: 'faq'
      get 'declaration-of-conformity', to: 'pages#declaration_of_conformity', as: 'declaration_of_conformity'

      # Contact Page / Support Cases
      resource :support_cases, only: [:create, :new], path_names: { new: 'new_support_case' } do
        get :success, on: :collection
      end

      # redirect using the url helper to respect route localization. ugly but it works
      get 'kontakt', to: redirect { |_, _| Rails.application.routes.url_helpers.new_support_cases_path }

      # Workshop
      get 'workshop', to: 'pages#workshop', as: 'workshop'
      get 'autofit',  to: 'pages#autofit',  as: 'autofit'

      # App-related
      get 'app',     to: 'pages#app',     as: 'app'
      get 'apps',    to: 'pages#apps',    as: 'apps'
      get 'cars',    to: 'pages#cars',    as: 'cars'
      get 'roadmap', to: 'pages#roadmap', as: 'roadmap'

      # Press Material
      get 'press',            to: 'press_materials#index',      as: 'press_materials'
      get 'press/brand',      to: 'press_materials#brand',      as: 'press_materials_brand'
      get 'press/team',       to: 'press_materials#team',       as: 'press_materials_team'
      get 'press/app',        to: 'press_materials#app',        as: 'press_materials_app'
      get 'press/pace-link',  to: 'press_materials#pace_link',  as: 'press_materials_pace_link'
      get 'press/graphics',   to: 'press_materials#graphics',   as: 'press_materials_graphics'

      # Feature pages
      get 'features/automatic-emergency-call',  to: 'features#ecall',                as: 'ecall'
      get 'features/fuel-saving-trainer',       to: 'features#fuel_saving_trainer',  as: 'fuel_saving_trainer'
      get 'features/trouble-code-analysis',     to: 'features#trouble_code_analysis', as: 'trouble_code_analysis'
      get 'features/find-my-car',               to: 'features#find_my_car',          as: 'find_my_car'
      get 'features/logbook',                   to: 'features#logbook',              as: 'logbook'
      # old route – preserved as there might be old links somewhere pointing at this
      get 'features/automatisches-fahrtenbuch', to: 'features#automatic_logbook'
      # actual route: find-the-cheapest-gas-station
      get 'features/gas-station-finder',        to: 'features#gas_station_finder',   as: 'gas_station_finder'
      get 'features/fuel-cost-tracking',        to: 'features#fuel_cost_tracking',   as: 'fuel_cost_tracking'
      get 'features/performance-monitor',       to: 'features#performance_monitor',  as: 'performance_monitor'
      get 'features/traffic-monitor',           to: 'features#traffic_monitor',      as: 'traffic_monitor'

      # Endpoints for car finder
      get 'cars/query', to: 'cars#identify'
      get 'cars/:id',   to: 'cars#show'

      # Job adverts
      get 'jobs',        to: 'jobs#index',    as: 'jobs'
      get 'jobs/:slug',  to: 'jobs#show',     as: 'job'

      # Newsletter related routes
      post 'newsletter-sign-up',              to: 'subscribers#newsletter_create', as: 'newsletter'
      get 'newsletter-confirmation(/:list)',  to: 'subscribers#newsletter_after_confirm'
    end

    # Routes that we want to have under the german locale, but without translated route go here:

    # Magazine
    scope 'magazin' do
      get '', to: 'magazine#index', as: 'magazine', constraints: { locale: 'de' }

  # Redirect path without locale to locale equivalent path
  get '/*path', to: redirect("/#{I18n.locale}/%{path}"),
                constraints: lambda { |req|
                  !req.path.match(%r{^\/(404|422|500)$}) &&
                    !req.path.match(%r{^\/(#{I18n.available_locales.join("|")})\/.*})
                }

  # Redirect root to detected locale
  root to: 'application#redirect_to_localized_root', as: :redirected_root
end

除了这个 localized 块,没有什么让我觉得超级可疑的。这是否来自某些 gem?如果是这样,apps_path(locale: 'en') 请求是否在此 localized 块之外工作?

您可以在调整路由文件后在控制台上使用Rails.application.routes.url_helpers.app_path(locale: :en)进行测试。

我快速浏览了您的路线,de 路线也遇到了类似的问题。我认为你得到的 apps_path 路线将只允许你的 default locale 作为参数。

添加以下 option 为我解决了问题:

RouteTranslator.config do |config|
  config.generate_unlocalized_routes = true
end

这将正确生成未本地化的路由,因此您可以将多个语言环境传递给 apps_path.