简体   繁体   中英

Rails 5: How Do I Get My Error Pages in the Public Folder for Different Locales to Display Other than "en?

When I was converting my Rails apps from 3.2.13 to Rails 4 I asked this question: Rails 4 - Would Like To Do Custom Error Pages in Public Folder Using I18n . I found out that all I had to do was to create error files for each error code and locale. In my Rails 4 apps I had 404.en.html , 404.fr.html , 500.en.html and 500.fr.html in my public folder. They were working as expected.

I recently converted all of my Rails apps to Rails 5 but had not checked if this still worked until now. I redesigned one of my apps and upgraded to Rails 5.1.1. I recreated the error pages to my new website format. I'm trying to test my error pages in localhost before I deploy my changes to Heroku. I have the following temporary configuration in /config/environments/development.rb so I can see my error pages.

config.consider_all_requests_local = false
config.action_dispatch.show_exceptions = true

When I display my website in English and force an error the English error page 404.en.html displays as expected. However when I display the French version of the page and force the same error the English error page displays, not the French error page 404.fr.html . I verified several times that the text in the French error file is French, not English.

I've been searching on Stack Overflow and on the web in general but I'm not finding any information about how to do this for Rails 5. Just about all of it is for Rails 2, 3 or 4.

I decided to deploy to Heroku to see if maybe the issue was with my testing using localhost. Unfortunately I have the same problem.

I searched again and saw that in the Rails documentation they use rescue pages so I did a search on the Guides site for 5.0 and found the following about Localized views which briefly mentioned rescue files.

application_controller

before_action :set_locale

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

private

  def set_locale
    I18n.locale = (params[:locale] if params[:locale].present?) || cookies[:locale] || I18n.default_locale || 'en'
    cookies[:locale] = I18n.locale if cookies[:locale] != I18n.locale
  end

Here is my log where the locale is "es"

Started GET "/es" for 127.0.0.1 at 2017-08-12 10:00:34 -0500 Processing by PagesController#home as HTML Parameters: {"locale"=>"es"} es

Here is how the English error page displays with locale es. When I click on any link on this page it displays the Spanish version of the website which I expect since the locale is es.

在此处输入图片说明

Here is the es error page in my public folder. You will see the text is in Spanish, not English.

在此处输入图片说明

Seems to be working fine on rails 5 (5.1.3). This is how myapp sets the locale in before_action

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

And this request http://localhost:3000/users/invalid_id?locale=en renders en EN错误

and http://localhost:3000/users/invalid_id?locale=fr renders french 错误错误

My guess would be that you are not setting locale properly in before_action .

Do Rails.logger.info I18n.locale to log used locales in your before_action to debug it further.

One way to add internationalization to your error pages would be to add custom route to a controller and using yml file on config/locales to implement content in different languages.

First, define error routes and set up a controller to handle those routes

config/routes.rb

AwesomeApp::Application.routes.draw do
  # custom error routes
  match '/404' => 'errors#not_found', :via => :all
  match '/422' => 'errors#unprocessable_entity', :via => :all
  match '/500' => 'errors#internal_server_error', :via => :all

  ...
end

app/controllers/errors_controller.rb

class ErrorsController < ApplicationController
  def internal_server_error
    render(:status => 500)
  end

  def not_found
    render(:status => 404)
  end

  def unprocessable_entity
    render(:status => 422)
  end
end

Then, add I18n definitions configuration for different languages.
For example, for English and French:

config/locales/en.yml

en:
  page_not_found: "The page you were looking for doesn't exist."

config/locales/fr.yml

fr:
  page_not_found: "La page que vous recherchiez n'existe pas."

Then, use it on the corresponding view files of the ErrorController 's actions. Based on you I18n.locale value, the views will be translated to desired language.

app/views/errors/not_found.html.erb

<div class="container">
  <div class="row">
    <div class="align-center">
      <h3><%= t('page_not_found') %></h3>
    </div>
  </div>
</div>

This is a much cleaner way to setup error pages than maintaining different files for different errors on your public folder.

UPDATE

As suggested, this configuration is required on config/application.rb for this to work:

config.exceptions_app = self.routes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM