Ruby on rails 3.1 具有可选范围的轨道路线";:地点“;

Ruby on rails 3.1 具有可选范围的轨道路线";:地点“;,ruby-on-rails-3.1,url-routing,Ruby On Rails 3.1,Url Routing,我正在开发Rails 3.1应用程序,我想为该应用程序将支持的不同语言设置特定的路由 /es/countries /de/countries … 对于默认语言('en'),我不希望在url中显示区域设置 /countries 这是我设置的路线定义 scope "(:locale)", :locale => /es|de/ do resources :countries end 它工作得很好,直到我尝试使用带有“en”作为区域设置的路径帮助器 在控制台中: app.countri

我正在开发Rails 3.1应用程序,我想为该应用程序将支持的不同语言设置特定的路由

/es/countries
/de/countries
…
对于默认语言('en'),我不希望在url中显示区域设置

/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”语言环境,不应该将语言环境参数添加到url中


谢谢

如果您不需要查询字符串,则无需将其传递给帮助者:

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"

我终于想出了如何轻松地做到这一点。您只需在应用程序控制器中设置默认的\u url\u选项,如下所示

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

这样,您可以确保区域设置不会发送到路径帮助程序。

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

在routes.rb中

scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/, defaults: {locale: "en"} do
正如MegaTux所说,在作用域中设置
默认值:{locale:“en”}

优势: jlfenaux解决方案适用于大多数环境,但并非所有环境。在某些上下文中(基本上与主控制器和视图之外的任何内容一样),路径帮助程序会感到困惑,并将object或object.id放入
locale
参数中,这将导致错误。您会发现自己将
locale:nil
放在许多路径帮助程序中以避免这些错误

可能的问题:
似乎
默认值:{locale:“en”}
总是覆盖为
locale
传递的任何其他值。该选项名为
default
,因此我希望它仅在没有值时才将locale指定给“en”,但实际情况并非如此。还有其他人经历过这种情况吗?

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

config/application.rb: config/routes.rb app/controllers/application_controller.rb:
如果您决定将
默认\u url\u选项
放在
应用程序\u控制器
中以修复路径帮助程序,请记住,您可能也想将其放在管理员的应用程序\u控制器中

在我的案例中,我使用此技术解决了此问题:

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
class ApplicationController{
如果设计控制器?
“设计”
结束
}
在\u操作之前:设置\u区域设置
def set_语言环境
I18n.locale=params[:locale]| | I18n.default_locale
结束
def url_选项
{:locale=>I18n.locale}.merge(超级)
结束
结束

我知道这一点。但是我在视图中使用的代码是为所有地区设计的,因此我必须将其传递给帮助器。我不想每次都测试当地人是不是…你的问题比你的答案更能回答我的问题。用括号括起:locale。谢谢,这就是我要找的。或者在范围定义中设置默认值:
scope“(:locale)”,locale:/en | es/,默认值:{locale:“en”}do
不幸的是,这会覆盖其他localesperfect!routesI中不需要默认设置我也有同样的问题。是的,同样的问题。总是把en当作默认值是的。同样的问题。有人能解决这个缺点吗?我不确定是否会像问题所问的那样在url中显示en-但我发现这个答案很有帮助,但我意识到我的所有链接,即使UI语言不是英语,也以英语作为其区域设置。因此,我必须将默认语言环境设置为jifenaux在接受的答案中所做的设置,而不是这个答案在routes文件中所做的设置。请确保使用字符串!您可以将根路径放入
区域设置范围
,不再需要get路由
root_path = 'pages#welcome'

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

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

def default_url_options(options = {})
  if I18n.default_locale != I18n.locale
    {locale: I18n.locale}.merge options
  else
    {locale: nil}.merge options
  end
end
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