2012-12-20 28 views
7

Tôi đang trong quá trình thêm quốc tế vào ứng dụng Rails và có nhiều hoặc ít theo dõi Rails GuideRailscast có liên quan.Cách định cấu hình các tuyến đường Rails để phù hợp với i18n

tôi đã chạy vào hai vấn đề:

  1. Làm thế nào tôi có thể thêm một "nhà" liên kết để chuyển hướng đến miền địa phương hiện nay. Hiện tại tôi có các liên kết root_path, nhưng chúng không thành công do dòng trong routes.rb được thiết kế để nhận rễ chưa được phát hiện. Điều này có nghĩa là root_path luôn hướng đến ngôn ngữ mặc định, không phải là ngôn ngữ hiện tại.
  2. Tôi có mọi thứ được thiết lập và hoạt động tại địa phương (ngoại trừ số ở trên) nhưng việc triển khai cho Heroku tất cả các url xuất hiện là rơi thông qua các tệp tuyến đường của tôi và bị bắt bởi một trong số tất cả. Họ đang chuyển hướng đến '/' theo ngôn ngữ defulat .

bộ My lên như sau

application_controller.rb

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

private 
def set_locale 
    I18n.locale = params[:locale] if params[:locale].present? 
end 

routes.rb

scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do 
    all_my_routes 

    # handles /valid-locale 
    root to: 'home#index', as: "localized_root" 
    # handles /valid-locale/fake-path 
    match '*path', to: redirect { |params, request| "/#{params[:locale]}" } 
end 

# handles/
root to: redirect("/#{I18n.default_locale}") 

# handles /bad-locale|anything/valid-path 
match '/*locale/*path', to: redirect("/#{I18n.default_locale}/%{path}") 

# handles /anything|valid-path-but-no-locale 
match '/*path', to: redirect("/#{I18n.default_locale}/%{path}") 

liên kết nhà của tôi:

<%= link_to "Home", root_path %> 

Trả lời

9

Tôi cuối cùng đã làm việc này sau một số qua lại. Vấn đề là bắt tất cả các tuyến đường là a) bắt nhiều hơn tôi dự đoán, và b) dường như hành xử khác nhau trong phát triển so với triển khai (tại sao điều này nên tôi không chắc chắn).

Dù sao, lần đầu tiên tôi đã thay đổi phạm vi để làm cho nó không bắt buộc (chú ý dấu ngoặc đơn):

scope "(:locale)", ..... 

này đảm bảo rằng scoped tuyến đường có giá trị ngay cả khi không locale được thiết lập (điều này chủ yếu là để xử lý một số vấn đề tôi đã trải nghiệm với các cuộc gọi lại, v.v.)

Điều này cho phép tôi để thả hai root to dòng, chỉ giữ lại

root to "home#index" 

Anh đã đánh rơi những "tay cầm/valid-locale/giả-path" dòng, điều này đã gây ra vấn đề với '/' đường dẫn.

Sau đó giữ tất cả các thông tin sau đây sau khi phạm vi (lưu ý điều cuối cùng).

# handles /bad-locale|anything/valid-path 
match '/*locale/*path', to: redirect("/#{I18n.default_locale}/%{path}") 

# handles /anything|valid-path-but-no-locale 
match '/*path', to: redirect("/#{I18n.default_locale}/%{path}"), constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" } 

# handles/
match '', to: redirect("/#{I18n.locale}") 

Là một điểm đáng chú ý, tôi cũng phải cập nhật action_mailer để xử lý url được bản địa hóa mới.

config.action_mailer.default_url_options = { :host => 'path.to.my.app.com', :locale => I18n.locale } 

Và bây giờ tất cả dường như đang hoạt động!

+1

Tuyệt vời mà bạn đã có thể làm cho nó hoạt động theo cách bạn muốn. Nếu tôi sẽ thay đổi bất cứ điều gì, tôi đoán rằng vì bạn đã chọn cách sử dụng 'I18n.locale' làm tất cả, bạn có thể sử dụng nó trong tất cả các lệnh' match' khác thay vì 'I18n .default_locale', vì bạn đang chuyển hướng đến "miền địa phương đã biết cuối cùng" thay vì "Tôi không biết bạn muốn ngôn ngữ nào để bạn có được ngôn ngữ mặc định của ứng dụng". Ngoài ra, bạn đã viết kiểm tra định tuyến chưa? Nếu có, và bạn có thể chia sẻ chúng, vui lòng chỉnh sửa câu trả lời của bạn và đăng câu trả lời cho lợi ích của mọi người. –

5

Có một viên ngọc làm công việc này một cách tuyệt vời. (https://github.com/svenfuchs/routing-filter) Bạn nên thêm đoạn mã sau vào Gemfile của bạn:

gem 'routing-filter' 

Và thêm dòng sau vào tập tin routes.rb của bạn

Rails.application.routes.draw do 
    filter :locale 
    ... 
end 

Hy vọng nó sẽ giúp ...

+0

cảm ơn Kzu, trông giống như một viên ngọc thú vị, và cái tôi chưa từng gặp trước đây. Nhưng tôi nghĩ rằng nó có thể là quá mức cần thiết trong trường hợp này. Đây phải là một trường hợp sử dụng khá chuẩn? Đặc biệt với vấn đề đầu tiên, tôi không thể không nghĩ rằng tôi đã bỏ qua một cái gì đó hiển nhiên (không chắc chắn những gì đang xảy ra RE Heroku ở giai đoạn này !!). Đánh giá cao bất kỳ ý tưởng nào bạn có thể có. –

+0

Ksu, tôi đã sẵn sàng gửi câu hỏi về định tuyến và thấy câu trả lời của bạn. Tôi đã thấy viên đá quý này nhưng tôi đoán tôi hơi mệt và không có được những gì tôi cần làm. Nó hoạt động rất tốt. –

0

Hình như bạn đã có thể sử dụng the comment I wrote trên Railscasts để trợ giúp với định tuyến I18n của bạn. Mát mẻ!

Đối với vấn đề đầu tiên của bạn, bạn có thể chỉ cần định tuyến lại root to: redirect("/#{I18n.default_locale}") để chuyển hướng đến I18n.locale thay thế không?

Đối với vấn đề thứ hai của bạn, bạn có sử dụng các bài kiểm tra trong bình luận Railscast hay có các bài kiểm tra của riêng bạn, và nếu có, chúng có vượt qua không? Heroku có cung cấp cho bạn bất kỳ nhật ký lỗi nào không? ($ heroku logs). Tôi có những tuyến đường được triển khai để Heroku làm việc như mong đợi, vì vậy tôi nghĩ rằng có một cơ hội nó không phải là một vấn đề với Heroku.

+0

hi @paul, vâng tôi đã "mượn" một số mã của bạn. Cảm ơn! Tôi đã cố gắng làm việc này với một vài chỉnh sửa, tôi sẽ đăng mô tả các bước của tôi. –

+0

suy nghĩ hoặc phê bình về giải pháp của tôi được nhiều hơn sau đó chào đón –

6

blogpost này giải thích nó thực sự rất chi tiết:

Chỉ cần những gì tôi đang tìm kiếm khi không có gì dường như làm việc

http://dhampik.com/blog/rails-routes-tricks-with-locales

scope "/:locale", locale: /#{I18n.available_locales.join("|")}/ do 
    resources :posts  
    root to: "main#index" 
    end 

    root to: redirect("/#{I18n.default_locale}", status: 302), as: :redirected_root 

    get "/*path", to: redirect("/#{I18n.default_locale}/%{path}", status: 302), constraints: {path: /(?!(#{I18n.available_locales.join("|")})\/).*/}, format: false 

chuyển hướng để mặc định lang từ gốc và hiện rất nhiều của những thứ khác nữa.

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