ที่ใช้ทำ localization
ได้เรื่องเลย เรื่องนี้เป็นเรื่องที่ผม postpone มานานแล้ว
เห็นทำ app ภาษาไทยได้ก็พอใจแล้ว ยังไม่ได้มองกรณีทำหลายภาษาเลย
หลังจากสั่ง
gem install ri18n
ก็ได้ source code มาจำนวนหนึ่ง
ตัวเอกสารไม่ต้องพูดถึง มีน้อยมาก
การใช้งานพึงแกะจาก source code เป็นหลัก
Note: ผมแกะมาพอให้เริ่มใช้งานได้นะครับ
ยังมีรายละเอียดอีกจำนวนหนึ่งที่ยังไม่ได้ดู
เช่น catalog, interpolation, phurals form
การใช้งาน ri18n กับ RoR
- Environment Setup
แก้ไข file config/environment.rb
เพิ่มเนื้อหาส่วนนี้ลงไป# Include your app's configuration here:
require 'i18nservice'
I18nService.instance.po_dir="#{RAILS_ROOT}/i18n"
ให้สังเกตว่าเราจะมี directory ที่ชื่อ i18n ที่จะไว้ใช้เก็บ
po file (translation file)
ข้อสังเกตอีกอัน ก็คือ I18nService ใช้ sigleton pattern
ดังนั้นเราจึง access ผ่าน instance attribute - การแสดง message ใน views
ในการ render output ใน rhtml
แทนที่จะเขียนออกไปตรงๆ เราจะใช้สัญญลักษณ์ _('msgid') แทนที่ msg ที่เราต้องการ<html>
<head>
<title>hello</title>
</head>
<body>
<p>
<%= _('hello') %>
</p>
</body>
</html> - เพิ่ม Task i18n ใน Rakefile
โดย ri18n ได้เตรียม Rake Task ที่ชื่อ gettext ไว้แล้ว
gettext นี้มีหน้าที่ scan file เพื่อหา msg ที่ต้องการทำ translation
เพื่อทำการ genereate .po file ให้เรา...
require 'gettext'
require 'i18nservice'
...
RAILS_ROOT=File.dirname(__FILE__)
...
desc "generate po (i18n) file"
Rake::GettextTask.new { |gettext|
gettext.source_files = FileList['**/*.rhtml']
gettext.new_langs = ['th','en']
I18nService.instance.po_dir="#{RAILS_ROOT}/i18n"
}
desc "create directory for i18n po file"
task :mki18ndir do
Dir.mkdir("i18n") unless File.exists?("i18n")
end
task :i18n => [:mki18ndir, :gettext]
จะเห็นได้ว่าเรามีการ config task class ที่ชื่อ Rake::GettextTask
โดยระบุว่าให้ scan message ที่ต้องการแปลงจาก file ที่มีนามสกุลเป็น rhtml
และระบุด้วยว่า ให้สร้าง po file สำหรับ language 2 ภาษา ก็คือ thai (th) กับ english (en)
Note: ผมทำแบบ struts ก็คือ ใน views ระบุเป็น message id
เราสามารถทำอีกแบบได้ ก็คือ ใน views เป็น english แล้วทำเฉพาะส่วนแปลเป็น th - generate po file
โดยใช้คำสั่งrake i18n
จะได้ file ออกมา 2 file ก็คือ th.po กับ en.po - ทำการแปล
โดยการ add message ที่ต้องการลงไปใน po file
ขั้นนี้ผมยังไม่ได้ลองเรื่อง encoding เลย
ที่ทดลองทำก็คือแค่ใช้ editor ที่ save encoding เป็น utf-8 ได้
ทำการ edit file เพิ่มเนื้อหา ภาษาไทย ลงใน file th.po
ส่วน file en.po ก็เพิ่มส่วน ภาษาอังกฤษ ลงไป
ตัวอย่าง file th.poÔªø# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Free Software Foundation, Inc.
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"POT-Creation-Date: 2002-12-10 22:11+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n == 0;\n"
msgid "hello"
msgstr "สวัสดีครับ"
Note: ผมยังไม่ได้ดูเรื่อง header ใน po file เลย
ใช้ค่า default ไปก่อน (ซึ่งมันก็ทำงานได้) - การเลือกใช้ language
เราสามารถเลือกใช้ language ที่ต้องการได้โดย
การสั่งI18nService.instance.lang='th'
โดยในตัวอย่างนี้ผมใส่ไว้ใน controller โดย check ว่ามี
parameter ที่ชื่อ lang pass มาหรือไม่ ถ้าไม่มีก็ให้ default เป็น thaiclass MainController < ApplicationController
def index
lang = params[:lang]
lang = "th" if lang == nil
I18nService.instance.lang=lang
end
end
ทำเสร็จแล้ว ก็ start server ทดสอบได้เลย
ผลลัพท์ที่ได้ก็เป็นที่น่าพอใจ
ส่วนประเด็นที่เหลือ ก็อาจจะเป็นการเรื่องการจัดการ po file
กรณีที่มีการแก้ไขเพิ่มเติม views แล้วเราสามารถ regenerate เป็นแบบ partial
ได้ไหม (อันนี้ยังไม่ได้ลองแกะดู แต่เท่าที่ลองสั่งมันมี message แปลก display ขึ้นมา)