Rails – Đa ngôn ngữ – Phần 1


Được đăng vào ngày 12/12/2016 | 0 bình luận
Rails – Đa ngôn ngữ – Phần 1
5 (100%) 2 votes

Chúng ta sẽ dùng I18n để hiển thị website trên nhiều ngôn ngữ khác nhau.

Đa ngôn ngữ là một bài toán khó, do đó chúng ta sẽ không thực hiện bằng cách dịch bình thường, mà thay vào đó là các chuỗi text cố định sẽ được hiển thị khác nhau với từng ngôn ngữ khác nhau.

Mặc định thì các ứng dụng Rails đều sử dụng I18n rồi, và ngôn ngữ duy nhất được sử dụng là tiếng Anh, các file ngôn ngữ sẽ được đặt trong thư mục config/locale với đuôi .yml, mặc định thư mục này chứa 1 file là en.yml:

# Files in the config/locales directory are used for internationalization
# and are automatically loaded by Rails. If you want to use locales other
# than English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
# I18n.t 'hello'
#
# In views, this is aliased to just `t`:
#
# <%= t('hello') %>
#
# To use a different locale, set it with `I18n.locale`:
#
# I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# To learn more, please read the Rails Internationalization guide
# available at http://guides.rubyonrails.org/i18n.html.

en:
 hello: "Hello world"

Chúng ta sẽ làm việc với các file này sau.

Bây giờ chúng ta sẽ thêm chức năng hỗ trợ URL đa ngôn ngữ.

Chúng ta sẽ đưa tham số ngôn ngữ vào sau đuôi URL, ví dụ http://localhost:3000/en/products.

Đầu tiên chúng ta sửa lại file routes.rb trong thư mục config như sau:

Rails.application.routes.draw do
    get 'admin/index'
    get 'sessions/new'
    get 'sessions/create'
    get 'sessions/destroy' 
    get 'store/index' 
 
    get 'admin' => 'admin#index'
 
    controller :sessions do
        get 'login' => :new
        post 'login' => :create
        delete 'logout' => :destroy
    end
 
    scope '(:locale)' do
        resources :users
        resources :orders
        resources :line_items
        resources :carts
        resources :products do
            get :who_bought, :on => :member
        end
        root :to => 'store#index', :as => 'store'
    end
end

Chúng ta gom các đoạn routing cho model – tức là các phương thức resources vào trong phương thức scope.

Phương thức scope ':locale' sẽ nối chuỗi trong biến :locale vào trước URL, tức là /products thì sẽ là en/products, ở đây chúng ta bọc :locale trong cặp dấu ngoặc tròn (), tức là có thể dùng hoặc không dùng cũng được.

Tiếp theo chúng ta cần khai báo biến :locale đó, chúng ta sửa lại lớp ApplicationController như sau:

class ApplicationController < ActionController::Base
    # Prevent CSRF attacks by raising an exception.
    # For APIs, you may want to use :null_session instead.
    before_filter :authorize
    before_filter :set_i18n_locale
 
    protect_from_forgery with: :exception
 
  private
 
    def current_cart
        Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
        cart = Cart.create
        session[:cart_id] = cart.id
        cart
    end
 
    helper_method :current_cart
 
  protected
 
    def authorize
        @user = User.find_by_id(session[:user_id]) 
        if @user == nil
            redirect_to '/login', :notice => 'You must login first'
        end
    end
 
    def set_i18n_locale 
        if params[:locale] 
            if I18n.available_locales.include?(params[:locale].to_sym)
                I18n.locale = params[:locale] 
            else
                flash.now[:notice] = params[:locale] + ' is not supported'               
            end
        end
    end
 
    def default_url_options 
        { :locale => I18n.locale }
    end
end

Phương thức set_i18n_locale sẽ được dùng trong phương thức before_filter, ở đây phương thức này sẽ kiểm tra xem trong URL gửi lên có tham số nào là :locale hay không, nếu có thì kiểm tra xem tham số đó có trong danh sách ngôn ngữ của I18n không, nếu có thì gán giá trị của tham số đó vào thuộc tính I18n.locale, không thì hiển thị lỗi.

Phương thức default_url_options là phương thức có sẵn của lớp ActionController::Base, phương thức này làm nhiệm vụ thiết lập các tham số trong lệnh HTTP được gửi lên. Chúng ta override phương thức này, ở đây chúng ta khai báo biến :locale có giá trị là giá trị của thuộc tính I18n.locale, tham số này sẽ được dùng trong phương thức helper là url_for.

Chúng ta sẽ tiếp tục làm việc với các phương thức này sau. Bây giờ nếu chúng ta trỏ đến URL http://localhost:3000/en/products thì sẽ không có gì khác biệt, còn nếu truyền vào một giá trị khác như http://localhost:3000/vi/products thì sẽ có dòng thông báo như ‘vi is not supported’.







Bình luận

Hãy trở thành người đầu tiên bình luận

Thông báo cho tôi qua email khi
avatar
wpDiscuz