Маршруты Rails с дополнительной областью ": locale"
Я работаю над приложением 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".
Есть ли способ сказать рельсы, что с "en" locale параметр locale не должен быть добавлен в URL?
Спасибо
Ответы
Ответ 1
Наконец-то я понял, как это сделать. Вам просто нужно установить default_url_options в контроллере приложения, как показано ниже.
def default_url_options(options={})
{ :locale => I18n.locale == I18n.default_locale ? nil : I18n.locale }
end
Таким образом, вы уверены, что языковой стандарт не отправляется в помощники путей.
Ответ 2
Это ДОЛЖНО быть лучшим решением:
В ваших route.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
, поэтому я ожидаю, что она присвоит locale 'en' только тогда, когда уже нет значения, но это не то, что происходит. Кто-нибудь еще испытывает это?
Ответ 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"
Ответ 4
Я делаю комбинацию того, что делают @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
Ответ 5
Если вы решили поместить default_url_options
в application_controller
для исправления ваших помощников пути, имейте в виду, что вы можете захотеть поместить его и в admin admin application_contoller.
Ответ 6
В моем случае я решил эту проблему с помощью этой техники:
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