带有可选范围“:locale”的Rails路由

时间:2011-11-22 09:04:58

标签: ruby-on-rails-3.1 url-routing

我正在研究Rails 3.1应用程序,我想为应用程序支持的不同语言设置特定路由。

/es/countries
/de/countries
…

对于默认语言('en'),我不希望语​​言环境显示在网址中。

/countries

这是我设定的路线定义。

scope "(:locale)", :locale => /es|de/ do
   resources :countries
end

它非常有用,直到我尝试使用带有'en'的路径助手作为语言环境。

在控制台中:

app.countries_path(:locale => 'fr')
 => "/fr/countries" 

app.countries_path(:locale => 'en')
 => "/countries?locale=en" 

我不想要“?locale = en”。

有没有办法告诉rails使用'en'语言环境,不应该将语言环境参数添加到网址?

由于

6 个答案:

答案 0 :(得分:21)

这应该是一个更好的解决方案:

在你的routes.rb中,

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

正如MegaTux所说,在范围内设置defaults: {locale: "en"}

优点: jlfenaux解决方案适用于大多数情况,但不是全部。在某些上下文中(基本上是主控制器和视图之外的任何内容),路径助手会混淆并将对象或object.id放在locale参数中,这将导致错误。您会发现自己将locale: nil放在许多路径助手中以避免这些错误。

可能存在的问题: defaults: {locale: "en"}似乎总是覆盖您传递给locale的任何其他值。该选项名为default,因此我希望它将区域设置分配给' en'只有在没有价值的情况下,才会发生这种情况。有其他人经历过这个吗?

答案 1 :(得分:16)

我终于想出了如何轻松地做到这一点。您只需在app控制器中设置default_url_options,如下所示。

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

这样,您确定区域设置不会发送到路径助手。

答案 2 :(得分:3)

如果您不想要查询字符串,则不必将其传递给帮助程序:

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"

答案 3 :(得分:3)

我正在做@Arcolye和@jifenaux正在做的事情的组合,加上一些额外的东西来保持代码尽可能干。它可能不适合所有人,但在我的情况下,每当我想支持新的语言环境时,我还必须在.yml中创建一个新的config/locales/文件,所以这就是它最适合的方式。我

配置/ 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

配置/ routes.rb中

root_path = 'pages#welcome'

scope '(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
  # ...
end

root to: root_path
get '/:locale', to: root_path

应用程序/控制器/ 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

答案 4 :(得分:0)

如果您决定将default_url_options放入application_controller来修复路径助手,请记住您可能还想将其放入管理员的application_contoller中

答案 5 :(得分:0)

就我而言,我使用以下技术解决了此问题:

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