2010-03-30 31 views
45

Tôi đang thêm I18N vào ứng dụng đường ray của mình bằng cách chuyển miền địa phương bằng cách sử dụng thông số url. Các url của tôi trông giống như http://example.com/en/usershttp://example.com/ar/users (đối với các ngôn ngữ tiếng Anh và tiếng Ả Rập tương ứng).Đường ray liên kết tới trang hiện tại và chuyển tham số tới trang

Trong tập tin tuyến đường của tôi, tôi đã xác định các tuyến đường của tôi với một: Tùy chọn path_prefix:

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

Và locale đang được thiết lập bằng cách sử dụng before_filter quy định tại ApplicationController

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

tôi cũng xác định ApplicationController # default_url_options, để thêm ngôn ngữ vào tất cả các url được tạo bởi ứng dụng:

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

Điều tôi muốn là thêm liên kết vào tiêu đề bố cục (được hiển thị trong tất cả các trang) sẽ liên kết đến cùng một trang nhưng với ngôn ngữ khác.

Ví dụ: nếu tôi đang duyệt ngôn ngữ arabic, tôi muốn liên kết "tiếng Anh" trong tiêu đề, sẽ chuyển hướng tôi trở lại trang hiện tại của tôi và đặt ngôn ngữ thành tiếng Anh. Có cách nào để làm điều này trong đường ray?

Trả lời

106

Đã cho tôi một thời gian để tìm thấy điều này nhưng đây là giải pháp của tôi:

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

Từ các tài liệu ở đây: http://api.rubyonrails.org/classes/ActionController/Base.html#M000649

Khi tạo một URL mới, thiếu giá trị có thể được điền vào từ các thông số yêu cầu hiện tại. Đối với ví dụ , url_for: action => ‘some_action‘ sẽ giữ lại bộ điều khiển hiện tại, như mong đợi. Hành vi này mở rộng đến các thông số khác, bao gồm : bộ điều khiển,: id và bất kỳ thông số nào khác được đặt vào đường dẫn của Tuyến đường.

Vì vậy, việc sử dụng url_for sẽ mặc định theo thông số của yêu cầu hiện tại, chỉ cần thay đổi thông số bạn muốn trong mã của bạn. Trong trường hợp này tất cả những gì tôi đã thay đổi là: locale, vì vậy mọi thứ khác vẫn giữ nguyên.

Lưu ý điều này cũng hoạt động cho "ẩn": tham số. Vì vậy, nếu bạn có:

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

bằng url trên cho trang/en/my_map sẽ không có 'home' trong url (tức là/en/home/my_map). Tiền thưởng.

+0

Thanx, đây sẽ là một giải pháp thanh lịch. Tuy nhiên, nó không hoạt động với các url an toàn: s – Faisal

+0

Điều này thật tuyệt vời và thanh lịch, tôi đã tìm kiếm một giải pháp như thế này trong nhiều giờ ... Tôi không hiểu tại sao nó không liên quan đến các url RESTful? bạn có thể đưa ra một ví dụ không ? – Alex

+2

Nếu bạn muốn chặn ngôn ngữ: url_for (: locale => nil) –

2

Bạn có thể phân tích cú pháp request_uri và thay thế ngôn ngữ của bạn trong đường dẫn bằng cụm từ thông dụng

Ok, đây là ví dụ về trợ giúp. Nếu tôi hiểu đúng mục tiêu

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" 

Đây là một điểm khởi đầu, vì vậy bạn có thể làm cho một số công cụ khác nhau mà bạn cần

+0

Tôi đã hy vọng một số người trợ giúp sẽ làm điều đó cho tôi. Nhưng cho đến nay, đây là giải pháp duy nhất tôi đã tìm thấy. Tôi đoán tôi sẽ làm một cái gì đó như request.request_uri.gsub (/ \/en \ //, '/ ar /') ... Điều đó nên làm thủ thuật Thanx cho đầu vào – Faisal

+0

Ok, tôi đã thêm mẫu helper – fl00r

1

Hãy xem điều này, mặc dù nó có thể không phải là DRY và phù hợp nhưng hoạt động hoàn hảo đối với tôi.Nó đọc tất cả các thông số bạn cung cấp thay thế chỉ url EX locale : http://example.com:3000/us/users?t=123&m=343 vv

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 
14

Vì vậy, tôi tìm thấy một cách để làm rõ ràng hơn điều này với ra dựa vào (càng nhiều) đường ray ma thuật.

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

Điều này sẽ hoạt động ở bất kỳ link_to nào.

Tất cả việc làm của nó là lấy các tham số của yêu cầu hiện tại và hợp nhất mã băm mong muốn mới vào chúng và sau đó tạo url mới cho điều đó.

+1

Đây là giải pháp tốt nhất - chung chung nhất. Cảm ơn bạn. –

+3

Giải pháp này hiển thị tất cả các thông số, ngay cả các thông số đã được gửi với POST, ví dụ: mật khẩu. Xin vui lòng không sử dụng nó. – Franz

+0

Không nếu bạn sử dụng các thông số mạnh như bạn dự định sẽ làm. ví dụ là psuedocode ... – Will

5

Liên kết đến trang hiện tại với địa phương khác nhau

Tested on Rails 4

Xin chào tất cả. Sau một thời gian nghiên cứu, tôi quyết định viết giải pháp của riêng mình cho việc này.

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

này hoạt động hoàn hảo, nhưng nó cho phép XSS Vulnerability thông số chỉ đi trong URL của bạn như dưới đây:

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

Hoặc trường hợp xấu nhất:

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 

Kiểm tra ra những gì URL bạn sẽ nhận được sau khi đi qua liên kết này trong ứng dụng của bạn.

Giải pháp sản xuất của tôi. Phương pháp "ngôn ngữ thay đổi" chuyển hướng đến bất kỳ trang nào có ngôn ngữ phù hợp chỉ sử dụng HTTP_REFERER trong đối tượng yêu cầu. Xin lưu ý: Phương pháp URI.path cho chỉ nhận được con đường, không phải toàn bộ url

Make "ngôn ngữ thay đổi" phương pháp trong bất kỳ điều khiển:

 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 

thêm video này vào cách bố trí của bạn

<%= 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 

Không có nhu cầu sử dụng params.merge hoặc bất kỳ giải pháp khỉ vá.

Tôi hy vọng điều này sẽ hữu ích, vì cá nhân tôi đã dành rất nhiều thời gian để giải quyết nó.

+0

Có lẽ quá muộn, nhưng ở đây tôi có một vấn đề: đường ray cho biết có một thiếu: tham số lang. Bất kỳ ý tưởng? –

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