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" )

2voto

Kelsey Hannan Points 1205

Vous pouvez en toute sécurité utilice url_for pour changer de langue avec url params si vous définissez only_path: true :

<%= link_to I18n.t('language_name', locale: I18n.locale), url_for( params.clone.permit!.merge(locale: locale, only_path: true ) %>

Nous .clone le site params avant de les autoriser tous ( .permit! ), pour préserver les paramètres forts ailleurs. La seule solution plus sûre que je puisse trouver serait de mettre tous les paramètres sur une liste blanche, ce qui prendrait beaucoup de temps...


Mise en œuvre robuste de l'I18n :

Ajouter un locales.rb pour définir ce que I18n.available_locales que vous soutenez :

# config/initializers/locales.rb

# Permitted locales available for the application
I18n.available_locales = [:en, :fr]

Définir un language_name dans le fichier de paramètres linguistiques de chaque langue (par ex. fr.yml ) :

fr:
  language_name: "Français"

Au fur et à mesure que vous ajoutez des langues, cet ERB vous permettra de passer d'une langue à l'autre de manière générique :

  // app/views/layouts/_languages.html.erb
  <span class="languages">
   <% I18n.available_locales.each do |locale| %>
      <% if I18n.locale == locale %>
        <%= link_to I18n.t('language_name', locale: locale), url_for( params.clone.permit!.merge(locale: locale, only_path: true ), {style: "display:none" } %>
      <% else %>
        <%= link_to I18n.t('language_name', locale: locale), url_for( params.clone.permit!.merge(locale: locale, only_path: true ) %>
      <% end %>
    <% end %>
  </span>

Pour le contrôleur, nous trouvons automatiquement la langue correcte pour l'utilisateur en détectant les paramètres de son navigateur. Accept-Language HTTP (en utilisant l'en-tête http_accept_language gemme).

Définir un session pour préserver les paramètres locaux entre les requêtes.

Ou, en option, utilisez default_url_options pour insérer le ?locale= dans l'url de votre application. Je fais les deux.

Contrôleur :

class ApplicationController < ActionController::Base
  before_action :set_locale

  private

  def set_locale
    I18n.locale = begin
      extract_locale ||
        session[:locale] ||
          http_accept_language.compatible_language_from(I18n.available_locales) ||
            I18n.default_locale
    end
    session[:locale] = I18n.locale
  end

  def extract_locale
    parsed_locale = params[:locale].dup
    I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
  end

  def default_url_options
    { locale: I18n.locale }
  end
end

2voto

CloudMagick Points 422

C'est ce qui a fonctionné pour moi, qui préserve les paramètres et protège contre le xss :

= link_to_unless_current "English", url_for( request.params.merge(locale: 'en'))

Vous pourriez utiliser link_to au lieu de link_to_unless_current

1voto

Santosh Bt Points 11

Jetez un coup d'œil à ce qui suit, bien que ce ne soit peut-être pas un système DRY et approprié, mais il fonctionne parfaitement pour moi. Il lit tous les paramètres que vous avez fournis en remplaçant seulement la locale. EX urls : http://example.com:3000/us/users?t=123&m=343 etc.

  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

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