Rails routes with optional scope “:locale”

前端 未结 6 1191
清歌不尽
清歌不尽 2020-12-06 06:08

I\'m working on a Rails 3.1 app and I\'d like to set specific routes for the different languages the app is going to support.

/es/countries
/de/countries
…
<         


        
相关标签:
6条回答
  • 2020-12-06 06:16

    This SHOULD be a better solution:

    In your routes.rb,

    scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/, defaults: {locale: "en"} do
    

    As MegaTux said, set defaults: {locale: "en"} in the scope.

    The advantage: The jlfenaux solution works in most contexts, but not all. In certain contexts (like basically anything outside of your main controllers and views), the path helpers will get confused and put the object or object.id in the locale parameter, which will cause errors. You'll find yourself putting locale: nil in lots of path helpers to avoid those errors.

    The possible problem: It seems that defaults: {locale: "en"} always overrides any other value you pass in for locale. The option is named default, so I'd expect it to assign locale to 'en' only when there's no value already, but that's not what happens. Anyone else experiencing this?

    0 讨论(0)
  • 2020-12-06 06:20

    If you decide to put default_url_options in the application_controller to fix your path helpers, keep in mind you might want to put it in your admin's application_contoller as well

    0 讨论(0)
  • 2020-12-06 06:20

    In my case I solved this problem using this technique:

    class ApplicationController < ActionController::Base
      layout -> {
        if devise_controller?
          'devise'
        end
      }
    
      before_action :set_locale
    
      def set_locale
         I18n.locale = params[:locale] || I18n.default_locale
      end
    
      def url_options
        { :locale => I18n.locale }.merge(super)
      end
    
    end
    
    0 讨论(0)
  • 2020-12-06 06:23

    I'm doing a combination of what @Arcolye and @jifenaux are doing, plus something extra to keep the code as DRY as possible. It might not be suitable for everybody, but in my case, whenever I want to support a new locale I also have to create a new .yml file in config/locales/ anyways, so this is how it works best for me.

    config/application.rb:

    locale_files = Dir["#{Rails.root}/config/locales/??.yml"]
    
    config.i18n.available_locales = locale_files.map do |d| 
      d.split('/').last.split('.').first
    end
    
    config.i18n.default_locale = :en
    

    config/routes.rb

    root_path = 'pages#welcome'
    
    scope '(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
      # ...
    end
    
    root to: root_path
    get '/:locale', to: root_path
    

    app/controllers/application_controller.rb:

    private
    
    def default_url_options(options = {})
      if I18n.default_locale != I18n.locale
        {locale: I18n.locale}.merge options
      else
        {locale: nil}.merge options
      end
    end
    
    0 讨论(0)
  • 2020-12-06 06:26

    I finally figured out how to do it easily. You just have to set the default_url_options in the app controller as below.

      def default_url_options(options={})
        { :locale => I18n.locale == I18n.default_locale ? nil : I18n.locale  }
      end
    

    This way, you are sure the locale isn't sent to the path helpers.

    0 讨论(0)
  • 2020-12-06 06:27

    If you don't want the query string you don't have to pass it to the helper:

    1.9.2 (main):0 > app.countries_path(:locale=>:de)
    => "/de/countries"
    1.9.2 (main):0 > app.countries_path
    => "/countries"
    1.9.2 (main):0 > app.countries_path(:locale=>:en)
    => "/countries?locale=en"
    1.9.2 (main):0 > app.countries_path
    => "/countries"
    1.9.2 (main):0 > app.countries_path(:locale=>nil)
    => "/countries"
    
    0 讨论(0)
提交回复
热议问题