2008-10-17 20 views
22

Làm thế nào tôi có thể đi về làm cho tuyến đường của tôi nhận ra một tham số tiền tố bắt buộc như sau:Tạo tuyến đường với một con đường bắt buộc tiền tố

/*lang/controller/id 

Trong đó phần lang là tùy chọn và có một giá trị mặc định nếu nó không được chỉ rõ trong URL:

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

EDIT

Lý tưởng nhất, tôi đang tìm cách để thực hiện điều này thông qua nhiều bộ điều khiển và hành động bằng cách ánh xạ một namespace:

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

Trong ví dụ của bạn, bạn chỉ tham khảo 1 bộ điều khiển, nhưng tôi mang nó bạn muốn tạo tuyến đường này cho mỗi bộ điều khiển? –

Trả lời

19

OK, tôi đã quản lý để sắp xếp ra vấn đề này:

không có cách nào để làm điều này trong Rails theo mặc định (ít nhất, chưa). Thay vì sử dụng không gian tên và giá trị mặc định, tôi cần cài đặt Sven Fuchs' routing filter.

Khi plugin được cài đặt, tôi đã thêm các file sau vào thư mục lib của tôi:

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 

tôi đã thêm dòng này để routes.rb:

map.filter 'locale' 

này về cơ bản điền vào một trước và sau khi móc, được tạo ra bởi các plugin, mà kết thúc tốt đẹp định tuyến đường ray.

Khi url được nhận dạng và trước khi Rails được thực hiện bất kỳ điều gì với nó, phương thức around_recognize được gọi. Điều này sẽ trích xuất một mã hai chữ cái đại diện cho miền địa phương, và vượt qua nó thông qua trong các params, mặc định là 'en' nếu không có miền địa phương được chỉ định.

Tương tự, khi url được tạo, tham số miền địa phương sẽ được đẩy vào URL ở bên trái.

này mang lại cho tôi các url và ánh xạ sau:

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

Tất cả những người giúp đỡ url hiện hoạt động như trước, với sự khác biệt duy nhất là trừ khi locale được chỉ định, nó được bảo tồn:

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

Cảm ơn lời khuyên, điều này rất hữu ích cho một số công việc dịch thuật/bản địa hóa/quốc tế hóa đang làm. FYI, bạn không phải thêm tệp đó vào thư viện của mình - bộ lọc 'ngôn ngữ' đã được đưa vào plugin. Tất cả những gì bạn cần làm là: 1. Cài đặt plugin. 2. Thêm 'map.filter 'locale'' vào routes.rb của bạn. Sau đó, nó chỉ bắt đầu hoạt động! Tốt đẹp. Tôi cũng đã thêm 'RoutingFilter :: Locale.include_default_locale = false' vào môi trường của tôi.rb để tránh'/en' nằm trong liên kết của tôi. Hoạt động tuyệt vời, tôi hy vọng plugin của Sven được đưa vào trong mã Rails I18n. –

+1

Đây là một tùy chọn khác mà tôi đã chạy qua ngày hôm nay, chưa xem xét nó (bộ lọc định tuyến đang hoạt động tốt) nhưng có thể được người khác quan tâm: http://github.com/raul/translate_routes –

+0

Bất kỳ ý tưởng nào về cách dịch vào Rails3? – dgilperez

1

Tôi đoán (không có thời gian để kiểm tra ngay bây giờ) mà điều này có thể làm việc:

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

OK, thử nó - nó hoạt động, on Rails 2.1.1 ít nhất. Vì vậy, đó là tốt. Mặc dù vậy, không thể có được ý tưởng mặc định là hoạt động, đó là một sự xấu hổ, bởi vì nó là DRYer.

2

Bạn có thể xác định các giá trị mặc định trong một tuyến đường bằng cách sử dụng phím :defaults. Hãy thử điều này:

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

Không hoạt động trong 2.1.1 trên máy của tôi. http: // localhost: 3000/posts/1 cho Không có kết quả phù hợp với tuyến đường "/ posts/1" với {: method =>: get} Có vẻ như: mặc định chỉ cung cấp thông số không có trong tuyến đường? Tôi cần phải điều tra: Tôi không biết về: mặc định ở tất cả, vì vậy cảm ơn! –

+0

Tôi nghĩ điều này đang đi đúng hướng - có thể tích hợp tùy chọn này với không gian tên và tài nguyên không? – Codebeef

+1

IIRC, mặc định hoạt động như giá trị mặc định trong tham số phương thức - nghĩa là mặc định chỉ có thể được sử dụng trên giá trị cuối cùng khi được liệt kê theo thứ tự, chứ không phải giá trị đầu tiên –

1

Giả sử bạn có thể cùng một lúc sử dụng [key] => để chỉ định tham số tùy chọn. Một cái gì đó như:

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

Tôi hiểu rằng câu hỏi cũ này, nhưng nó có thể hữu ích.

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

Và bạn phải thêm trước khi bộ lọc để điều khiển ứng dụng để xác định miền địa phương, chẳng hạn như

before_filter :define_locale 

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

Tiền tố đường dẫn không phải là tùy chọn, vì vậy bạn luôn phải cung cấp ngôn ngữ trừ khi bạn sao chép các tuyến bên ngoài khối. – dseifert

Các vấn đề liên quan