2011-12-05 12 views
19

Mam witrynę w języku francuskim i angielskim. Chcę, aby użytkownik mógł przełączać język w locie po kliknięciu łącza w nagłówku. Całkiem proste.Przełącz język z adresem URL w Ruby on Rails 3

Śledzę Ruby on Rails 3 przewodnik, i mam to:

class ApplicationController < ActionController::Base 
before_filter :set_locale 
def set_locale 
    I18n.locale = params[:locale] || I18n.default_locale 
end 

protect_from_forgery 

    def default_url_options(options={}) 
    logger.debug "default_url_options is passed options: #{options.inspect}\n" 
    { :locale => I18n.locale } 
    end 
end 

Moje trasy wyglądać następująco:

scope "(:locale)", :locale => /en|fr/ do 

match 'home' => 'home#index' 
match 'home/ajax_twitter' => 'home#ajax_twitter' 
match 'equipe' => 'equipe#index' 
match 'equipe/sylvain' => 'equipe#sylvain' 
match 'equipe/benoit' => 'equipe#benoit' 
match 'equipe/stephane' => 'equipe#stephane' 
match 'equipe/suemarie' => 'equipe#suemarie' 
match 'equipe/regis' => 'equipe#regis' 
match 'equipe/fred' => 'equipe#fred' 

match 'equipe/callback' => 'equipe#callback' 
match 'equipe/auth' => 'equipe#auth' 
match 'equipe/ajax_contact' => 'equipe#ajax_contact' 

match 'linkedinauth/callback' => 'linkedinAuth#callback' 
match 'linkedinauth/init_auth' => 'linkedinAuth#init_auth' 

match 'mission' => 'mission#index' 
match 'service' => 'service#index' 
match 'developmen' => 'developmen#index' 

match 'contact' => 'contact#index' 

match 'mandats' => 'mandats#index' 
end 

match '/:locale' => "home#index" 

I moim zdaniem zrobić to:

<% if I18n.locale == I18n.default_locale %> 
    <%= link_to "English", '/en'%> 

<% else %> 
    <%= link_to "Français", '/fr'%> 

<%end%> 

Wszystko działa dobrze na stronie głównej, ale jeśli spróbuję zmienić język, gdy jestem w określonym kontrolerze, wracam do h ome page. Próbowałem dodać to:

<% if I18n.locale == I18n.default_locale %> 
    <%= link_to "English", '/en/' + params[:controller]%> 

<% else %> 
    <%= link_to "Français", '/fr/' + params[:controller]%> 

<%end%> 

rozwiązuje ten kontroler, ale jeśli jesteśmy w konkretnym działaniu i ponownie zmienić język, wrócę do „indeksu” tego kontrolera.

Moje pytanie: Jaki jest najlepszy sposób, aby sobie z tym poradzić?

Chyba mógłbym zaimplementować coś w ApplicationController (filter), aby sprawdzić, czy kontroler/akcja/id jest przekazywany i dołączać do ustawień narodowych. Czy mogę to zrobić w routes.rb?

Odpowiedz

52

No cóż, w końcu znaleźli sposób lubię ...

<% if I18n.locale == I18n.default_locale %> 
    <%= link_to "English", { :locale=>'en' } %> 

<% else %> 
    <%= link_to "Français", { :locale=>'fr' } %> 

<%end%> 

takie proste!

Vive Ruby on Rails!

14

Jeśli masz trasę zakres takiego, który obejmuje wszystkie zlokalizowane tras:

scope "/:locale" do 
    ... 
end 

jeśli jesteś na stronie wewnątrz że trasa np scoped „/ En/...” można utworzyć łącza, aby zmienić ustawienia regionalne, nie zmieniając swoją aktualną lokalizację strony tak:

<%= link_to "Français", params.merge({:locale => :fr}) %> 
<%= link_to "English", params.merge({:locale => :en}) %> 
+1

Dla niektórych symboli przyczyny używanie (np. ': en') powoduje, że' ActionController :: RoutingError (No route matches {...}) 'na ** kolejnych ** kliknięciach (testowane w Rails 3.2.12). Używanie łańcuchów rozwiązuje problem (': locale => 'en''). – user569825

+0

jest to bardziej przydatna odpowiedź, ponieważ dotyczy istniejącego kontekstu, tj. Params. i łączenie ich z ustawieniami narodowymi, które są parametrem na poziomie meta ... – Jerome

3

Załóżmy, że chcesz selektor dla wszystkich języków. Na przykład.Jesteś w en lokalizacji i masz również fr i es lokalizacje

W application_helper.rb (lub innego pomocnika w/app/pomocników /)

def alternate_locales 
    I18n.available_locales.map{|l| 
    yield(l) 
    }.join.html_safe 
end 

Teraz gdziekolwiek w widoku:

<% alternate_locales do |l| %> 
    <li class="language <%= l %>"><%= link_to(l,locale: l) %></li> 
<% end %> 

Jeśli język użytkownika jest angielski, bieżący adres URL to www.example.com/en/path/ Zostanie wygenerowany:

<li class="language fr"><a href="www.example.com/fr/path/">fr</a></li> 
<li class="language es"><a href="www.example.com/es/path/">es</a></li> 
<li class="language en"><a href="www.example.com/en/path/">en</a></li> 

Plus, jeśli chcesz mieć link [rel = "alternate"] Odnośniki w nagłówku:

<% alternate_locales do |l| %> 
    <link rel="alternate" hreflang="<%= l %>" href="<%= url_for(locale: l) %>"> 
<% end %> 

To wygeneruje:

<link rel="alternate" hreflang="fr" href="www.example.com/fr/path/"> 
<link rel="alternate" hreflang="es" href="www.example.com/es/path/"> 
<link rel="alternate" hreflang="en" href="www.example.com/en/path/"> 
3

wierzę w ten sposób sprawia, że ​​odkurzacz. Więc o to idzie:

config/environment.rb

I18n.available_locales = [:en, :pt, :es, :de] 

Utwórz plik .yml dla każdej lokalizacji: na config/locales /: locale.yml

Czy nie zapomnij dodać to do każdego z plików locale.yml, tak jest tłumaczone link_to t(lang) podczas zmiany między lokalizacjami.

en: 
    en: "English" 
    pt: "Portuguese" 
    es: "Spanish" 
    de: "German" 

Dodaj listę locales do html:

<a class="dropdown-toggle" data-toggle="dropdown" href="#"> 
    <%= t(I18n.locale) %> # Current selected locales 
    <span class="caret"></span> 
</a> 
<ul class="dropdown-menu" role="menu"> 
    <li class="header">Select a language</li> 
     <% I18n.available_locales.each do |lang| %> # Array of available locales 
     <li> 
     <%= link_to t(lang), change_locale_path(lang) %> # Each locale URL param and name 
     </li> 
     <% end %> 
</ul> 

Więc teraz można zobaczyć wszystkie lokalizacje, które zostały dodane do config/environment.rb

config/Trasy .rb:

match 'lang/:locale', to: 'index#change_locale', as: :change_locale, via: [:get] 

APP/regulatory/index_controller.rb

def change_locale 
    l = params[:locale].to_s.strip.to_sym 
    l = I18n.default_locale unless I18n.available_locales.include?(l) 
    cookies.permanent[:my_locale] = l 
    redirect_to request.referer || root_url 
end 

APP/regulatory/application_controller.rb

before_action :set_locale 

def set_locale 
     if cookies[:my_locale] && I18n.available_locales.include?(cookies[:grolla_locale].to_sym) 
     l = cookies[:my_locale].to_sym 
     else 
     l = I18n.default_locale 
     cookies.permanent[:my_locale] = l 
     end 
     I18n.locale = l 
    end