2008-10-17 7 views
22

jaki sposób można przejść o tworzeniu moich tras rozpoznać opcjonalny parametr prefiks następująco:Tworzenie trasy z opcjonalnym przedrostkiem ścieżki

/*lang/controller/id 

że część lang jest opcjonalna i ma wartość domyślną, jeśli nie jest określona w adresie URL:

/en/posts/1 => lang = en 
/fr/posts/1 => lang = fr 
/posts/1  => lang = en 

EDIT

Idealnie szukam to zrobić w wielu kontrolerów i działań poprzez mapowanie Przestrzeń nazw:

map.namespace "*lang" do |lang| 
    lang.resources :posts 
    lang.resources :stories 
end 
+0

W przykładzie tylko odnośnik 1 kontroler, ale biorę go chcesz utworzyć tę trasę dla każdego kontroler? –

Odpowiedz

19

OK, udało mi się rozwiązać ten problem:

Nie ma możliwości zrobienia tego w Rails domyślnie (przynajmniej jeszcze nie). Zamiast używać przestrzeni nazw i wartości domyślnych, potrzebowałem zainstalować Sven Fuchs' routing filter.

Po zainstalowaniu wtyczki, dodałem następujący plik do mojego lib katalogu:

require 'routing_filter/base' 

module RoutingFilter 
    class Locale < Base 

    # remove the locale from the beginning of the path, pass the path 
    # to the given block and set it to the resulting params hash 
    def around_recognize(path, env, &block) 
     locale = nil 
     path.sub! %r(^/([a-zA-Z]{2})(?=/|$)) do locale = $1; '' end 
     returning yield do |params| 
     params[:locale] = locale || 'en' 
     end 
    end 

    def around_generate(*args, &block) 
     locale = args.extract_options!.delete(:locale) || 'en' 
     returning yield do |result| 
     if locale != 'en' 
      result.sub!(%r(^(http.?://[^/]*)?(.*))){ "#{$1}/#{locale}#{$2}" } 
     end 
     end 
    end 

    end 
end 

Dodałem tę linię do routes.rb:

map.filter 'locale' 

To w zasadzie wypełnia przed i po hakowaniu, generowanym przez wtyczkę, owijającym routing szyn.

Po rozpoznaniu adresu URL i wywołaniu przez Railsy cokolwiek z nim, wywoływana jest metoda around_recognize. Spowoduje to wyodrębnienie dwuliterowego kodu reprezentującego ustawienia narodowe i przekazanie go w parametrach, domyślnie "en", jeśli nie określono żadnych ustawień narodowych.

Podobnie, po wygenerowaniu adresu URL parametr ustawień narodowych zostanie przesunięty w adres URL po lewej stronie.

To daje mi następujące adresy URL i mapowania:

/ => :locale => 'en' 
/en => :locale => 'en' 
/fr => :locale => 'fr' 

Wszystkie istniejące pomocnicy URL działa tak jak poprzednio, z tą tylko różnicą, że o ile nie zostanie określone ustawienia narodowe, jest zachowana:

home_path     =>/
home_path(:locale => 'en') =>/
home_path(:locale => 'fr') => /fr 
+2

Dzięki za podpowiedź, działało to świetnie na potrzeby tłumaczenia/lokalizacji/internacjonalizacji I 'robię. FYI, nie musisz dodawać tego pliku do biblioteki - filtr "locale" jest już dołączony do wtyczki. Wszystko, co powinieneś zrobić, to: 1. Zainstaluj wtyczkę. 2. Dodaj 'map.filter 'locale'' do twoich routes.rb. Po tym zaczyna działać! Miły. Dodałem także 'RoutingFilter :: Locale.include_default_locale = false' do mojego environment.rb, aby uniknąć'/en' znajdującego się w moich linkach. Działa wspaniale, mam nadzieję, że wtyczka Svena zostanie wciągnięta w kod źródłowy Rails I18n. –

+1

Oto inna opcja, którą dziś spotkałem, nie zaglądałem do niej (filtr routingu działa świetnie), ale może zainteresować innych: http://github.com/raul/translate_routes –

+0

Wszelkie pomysły na przetłumaczenie tego do Rails3? – dgilperez

1

Zgaduję (nie ma czasu, aby przetestować teraz), że to może działać:

map.connect ':language/posts/:id', :controller => 'posts', :action => 'show' 
map.connect 'posts/:id', :controller => 'posts', :action => 'show' 

OK, próbowałem go - działa on Rails 2.1.1 przynajmniej. To dobrze. Nie można jednak uzyskać: domyślnego pomysłu do pracy, co jest wstydem, ponieważ jest to DRYer.

2

Możesz zdefiniować wartości domyślne na trasie, używając klucza :defaults. Wypróbuj to:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', 
           :defaults => { :lang => 'en' } 
+0

Nie działa w wersji 2.1.1 na moim komputerze. http: // localhost: 3000/posts/1 daje Brak dopasowań trasy "/ posts/1" za pomocą {: method =>: get} Wygląda tak: domyślnie dostarcza tylko parametry nie znajdujące się na trasie? Muszę zbadać: nie wiedziałem o: domyślnie, więc dziękuję! –

+0

Myślę, że jest to na dobrej drodze - czy możliwe jest zintegrowanie tej opcji z przestrzeniami nazw i zasobami? – Codebeef

+1

IIRC, wartości domyślne działają jak wartości domyślne w parametrach metody - tzn. Wartości domyślne mogą być używane tylko dla ostatnich wartości, gdy są wymienione w kolejności, a nie dla pierwszych wartości. –

1

Myślałem, że możesz za jednym razem użyć [klucza] => zero, aby określić opcjonalny parametr. Coś jak:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', :lang => nil 
2

Rozumiem, że to stare pytanie, ale może być przydatne.

map.with_options(:path_prefix => ":locale") do |m| 
    m.resources :posts 
    m.resources :stories   
    end 

I trzeba dodać przed filtrem do sterownika aplikacji, aby określić ustawienia regionalne, takie jak

before_filter :define_locale 

def define_locale 
    if params[:locale] == nil 
    I18n.locale = 'en' 
    else 
    I18n.locale = params[:locale] 
    end 
end 
+1

Prefiks ścieżki nie jest opcjonalny, więc zawsze musisz podać lokalizację, chyba że duplikujesz trasy poza blokiem. – dseifert