Rails ссылка на текущую страницу и передача ей параметров - PullRequest
46 голосов
/ 30 марта 2010

Я добавляю I18N в мое приложение rails, передавая локаль с помощью параметров url. Мои URL выглядят как http://example.com/en/users и http://example.com/ar/users (для английского и арабского языков соответственно).

В моем файле маршрутов я определил мои маршруты с параметром: path_prefix:

map.resources :users, :path_prefix => '/:locale'

И локаль устанавливается с помощью before_filter, определенного в ApplicationController

def set_locale
    I18n.locale = params[:locale]
end

Я также определил ApplicationController # default_url_options, чтобы добавить локаль ко всем URL, сгенерированным приложением:

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

Я хочу добавить в заголовок макета ссылку (отображаемую на всех страницах), которая будет ссылаться на ту же страницу, но с другой локалью.

Например, если я просматриваю арабскую локаль, я хочу ссылку "английский" в заголовке, которая перенаправит меня обратно на мою текущую страницу и установит локаль на английский. Есть ли способ сделать это в рельсах?

Ответы [ 6 ]

109 голосов
/ 29 апреля 2010

Мне понадобилось время, чтобы найти это, но вот мое решение:

link_to 'English', url_for( :locale => 'en' )
link_to 'Deutch', url_for( :locale => 'de' ) 

Из документов здесь: http://api.rubyonrails.org/classes/ActionController/Base.html#M000649

При создании нового URL отсутствует значения могут быть заполнены из параметры текущего запроса. За пример, url_for: action => ‘Some_action‘ сохранит текущий контроллер, как и ожидалось. Это поведение распространяется на другие параметры, в том числе : controller,: id и любые другие параметры, которые помещаются в Путь к маршруту.

Таким образом, использование url_for по умолчанию будет соответствовать параметрам текущего запроса, просто измените тот, который вы хотите в своем коде. В этом случае все, что я изменил, было: локаль, так что все остальное остается прежним.

Обратите внимание, что это также работает для "скрытых": параметров. Так что если у вас есть:

map.my_map ':locale/my_map', :controller => 'home', :action => 'my_map'

при использовании вышеуказанного url_for на странице / en / my_map не будет 'home' в URL (т.е. / en / home / my_map). Бонус.

14 голосов
/ 06 сентября 2012

Итак, я нашел способ более явно сделать это, не полагаясь на (столько же) магию рельсов.

url_for(params.merge({:your_new_parameter => value}))

Это должно работать в любом link_to.

Все, что он делает, берет параметры текущего запроса и объединяет в них ваш новый желаемый хеш, а затем создает для него новый URL.

5 голосов
/ 03 февраля 2016

Ссылка на текущую страницу с разными локалями

Проверено на рельсах 4

Привет всем. После некоторого времени исследований я решил написать собственное решение для этого.

link_to 'English', url_for( :locale => 'en' )
link_to 'Deutch', url_for( :locale => 'de' ) 

Это прекрасно работает, но допускает Уязвимость XSS , просто передающую параметры в ваш URL, как показано ниже:

http://localhost:3000/en/about?host=www.fishingsiteorbadurl.com/%23&port=80

Или в худшем случае:

http://localhost:3000/en/about?host=%D0%BE%D1%87%D0%B5%D0%BD%D1%8C%D0%BF%D0%BB%D0%BE%D1%85%D0%BE%D0%B9%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84

Проверьте, какие URL вы получите после перехода по этой ссылке в вашем приложении.

Мое производственное решение. Метод "изменить язык" перенаправляет на любую страницу с правильным языком, просто используя HTTP_REFERER в объекте запроса. Обратите внимание: метод URI.path для получения только пути, а не целого URL

Сделать метод "изменить язык" в любом контроллере:

        def change_lang

        if request.referer.nil?
                 refer = root_url
        else
                 uri = URI(request.referer)
                 refer = uri.path
        end
        lang = params[:lang]
        cookies[:locale] = lang
        redirect_to refer

        end

application_controller.rb

before_action :set_locale

def set_locale

# -- Get lang from cookies or url parameter locale

user_locale = cookies[:locale] || params[:locale]

# -- If present

if user_locale.present? 

    # -- If it is has 2 symbols

    user_locale = user_locale.scan(/[a-zA-Z]{2}/) 
else

    # -- If no - use default en locale

    user_locale = 'en'
end


# -- Check, is this locale available for using.
# Please note: this needed for disable invalid locale warning.

if I18n.available_locales.include?(user_locale[0].to_sym)

    I18n.locale =  user_locale[0]
else
    I18n.locale =   "en"
end

end

добавить это в свой макет

<%= link_to 'English', change_lang_path('en') %> <%= link_to 'Russian', change_lang_path('ru') %>

конфиг / routes.rb

scope "(:locale)", locale: /[a-zA-Z]{2}/ do
get "change_lang/:lang" => "users#change_lang", :as => "change_lang"
end

Нет необходимости использовать params.merge или любое другое решение.

Надеюсь, это поможет, потому что я лично потратил много времени на его решение.

2 голосов
/ 30 марта 2010

Вы можете проанализировать request_uri и заменить ваш языковой стандарт в пути регулярным выражением

Хорошо, вот вспомогательный пример. Если я правильно понимаю цель

def locale_url(url, locale)
  url.gsub(/\/\w*$/, "/#{locale}")
end

url = "http://www.domain.com/products/1/ru" # or request.request_uri
locale = "en"
locale_url(url, locale) #=> "http://www.domain.com/products/1/en"

Это отправная точка, так что вы можете делать разные вещи, которые вам нужны

1 голос
/ 28 марта 2012

Посмотрите на это, хотя это может быть не СУХОЙ и правильной, но отлично работает для меня. Он читает все заданные вами параметры, заменяя только локаль EX URL: http://example.com:3000/us/users?t=123&m=343 и т. Д.

  def us_link           
        link_to "US", form_locale_url("/us")            
  end

  def jp_link           
    link_to "Japan",form_locale_url("/jp")           
  end              

  def form_locale_url(locale)            
    new_url = request.request_uri          
    new_locale_url = new_us_url = new_jp_url = new_url           
    if new_url == "/"          
      new_locale_url.sub!(/\//,locale)           
    elsif (new_url =~/\/us/) == 0        
      new_us_url.sub!(/\/us/,locale)        
    elsif (new_url =~/\/jp/) == 0          
      new_jp_url.sub!(/\/jp/,locale)       
    end     
  end
0 голосов
/ 22 мая 2019

Гораздо более быстрый путь - и это удобно, если у вас много параметров, которые меняются в разных местах ... избегайте путаницы с тегом привязки, который просто объединяет новый параметр локали с существующим (и фактически убивает старый параметр локали) .

<%= link_to "ру", request.params.merge( locale: 'ru' ) %>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...