55 votes

Lien Rails vers la page courante et passage de paramètres à celle-ci

J'ajoute I18N à mon application rails en passant la locale en utilisant les paramètres de l'url. Mes urls ressemblent à http://example.com/en/users y http://example.com/ar/users (respectivement pour les langues anglaise et arabe).

Dans mon fichier de routes, j'ai défini mes routes avec une option :path_prefix :

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

Et la locale est définie à l'aide d'un before_filter défini dans ApplicationController.

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

J'ai également défini ApplicationController#default_url_options, pour ajouter la locale à toutes les urls générées par l'application :

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

Ce que je veux, c'est ajouter un lien dans l'en-tête de la mise en page (affiché sur toutes les pages) qui renverrait à la même page mais avec l'autre locale.

Par exemple, si je navigue dans la locale arabe, je veux un lien "English" dans l'en-tête, qui me redirigera vers ma page actuelle, et réglera la locale sur l'anglais. Existe-t-il un moyen de faire cela dans rails ?

0 votes

link_to "Refresh with a new GET param", params.merge( newKey: "newValue" )

123voto

pixelearth Points 2948

M'a fallu un certain temps pour trouver cela, mais voici ma solution:

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

À partir de la documentation ici: http://api.rubyonrails.org/classes/ActionController/Base.html#M000649

Lors de la génération d'une nouvelle URL, manquant les valeurs peuvent être remplis à partir de la la demande actuelle de paramètres. Pour exemple, url_for :action => ‘some_action " sera de maintenir le contrôleur, comme prévu. Ce comportement s'étend à d'autres paramètres, y compris :contrôleur :id, et tous les autres les paramètres qui sont placés dans un Route du chemin.

Donc, en utilisant url_for sera, par défaut, la demande actuelle de paramètres, il suffit de changer le son que vous voulez dans votre code. Dans ce cas, tout ce que je a changé :locale, de sorte que tout le reste reste le même.

Remarque cela fonctionne aussi pour les "cachés" :les paramètres. Donc, si vous avez:

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

à l'aide de la url_for dans la page /fr/my_map n'aura pas de 'maison' dans l'url (c'est à dire /fr/home/my_map). Bonus.

0 votes

Merci, ce serait une solution élégante. Cependant, elle ne fonctionne pas avec les restful urls :s

0 votes

C'est génial et élégant, j'ai cherché une solution comme celle-ci pendant des heures... Je ne comprends pas pourquoi il n'est pas compatible avec les urls RESTful. Pouvez-vous donner un exemple ?

2 votes

Si vous voulez supprimer la locale : url_for(:locale => nil)

19voto

Will Points 1782

J'ai donc trouvé un moyen de le faire de manière plus explicite sans recourir (autant) à la magie des rails.

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

Cela devrait fonctionner dans n'importe quel link_to .

Tout ce qu'il fait, c'est de prendre les paramètres de la requête actuelle et d'y intégrer le nouveau hachage souhaité, puis de créer une nouvelle url pour cela.

1 votes

C'est la meilleure solution - la plus générique. Merci.

6 votes

Cette solution expose tous les paramètres, même ceux qui ont été envoyés avec POST, par exemple les mots de passe. Veuillez ne pas l'utiliser.

0 votes

Pas si vous utilisez des paramètres forts comme vous êtes censé le faire. L'exemple est un pseudo-code...

6voto

Evgeniy B Points 174

Lien vers la page actuelle avec différentes locales

Testé sur Rails 4

Bonjour à tous. Après quelques temps de recherche, je décide d'écrire ma propre solution pour ce problème.

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

Cela fonctionne parfaitement, mais cela permet Vulnérabilité XSS Il suffit de passer des paramètres dans votre URL comme ci-dessous :

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

Ou dans le pire des cas :

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

Vérifiez les URLs que vous obtiendrez en passant par ce lien dans votre application.

Ma solution de production. La méthode "changer de langue" redirige vers n'importe quelle page avec la bonne locale en utilisant HTTP_REFERER dans l'objet de la demande. Attention : la méthode URI.path ne permet de récupérer que le chemin d'accès, pas l'url entière.

Faites la méthode "changer la langue" dans n'importe quel contrôleur :

        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

ajoutez ceci à votre mise en page

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

config/routes.rb

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

Il n'est pas nécessaire d'utiliser params.merge ou toute autre solution de fortune.

J'espère que cela vous aidera, car j'ai personnellement passé beaucoup de temps à le résoudre.

3voto

Jerome Points 342

Une solution beaucoup plus rapide - et pratique si vous avez beaucoup de paramètres qui changent à différents endroits... évitez le désordre avec une balise d'ancrage qui fusionne simplement le nouveau paramètre local avec les paramètres existants (et qui tue réellement l'ancien paramètre local).

<%= link_to "ру", request.params.merge( locale: 'ru' ) %>

Mais oui, il faut mettre les paramètres sur une liste blanche à ce stade, en fonction du contexte de l'application.

2voto

fl00r Points 41855

Vous pouvez analyser request_uri, et remplacer votre locale dans le chemin par une expression régulière

Ok, voici un exemple d'aide. Si je comprends bien l'objectif

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"

C'est un point de départ, donc vous pouvez faire des choses différentes selon vos besoins.

0 votes

J'espérais une aide qui le ferait pour moi. Mais jusqu'à présent, c'est la seule solution que j'ai trouvée. Je pense que je vais faire quelque chose comme request.request_uri.gsub(/\/en\//, '/ar/')... Cela devrait faire l'affaire. Merci pour votre contribution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X