ไลบรารี/เฟรมเวิร์กสำหรับการทำให้แอป/เว็บไซต์รองรับหลายภาษา/วัฒนธรรม หรือที่เรียกว่า “internationalization” ทั้งส่วนหน้าตาและการประมวลผลอื่นๆ เช่น เรียงลำดับตามพจนานุกรม ปฏิทิน รูปแบบวันเวลา สกุลเงิน
โพสต์เรื่องนี้ไปที่กรุ๊ปสมาคมโปรแกรมเมอร์ไทยและใน Medium ขอโพสต์ซ้ำที่นี่
อะไรคือ Internationalization?
หลักๆ ในเรื่องนี้มี 2 คำ คือ internationalization (i18n) กับ localization (L10n)
ส่วนของโค้ดจะเป็นการทำ internationalization รองรับไว้ คือเตรียมให้รองรับหลายภาษา/วัฒนธรรม ไม่ hardcode ภาษาลงในโค้ด คนเขียนโค้ดไม่ทึกทักเรื่องเกี่ยวกับภาษาและวัฒนธรรมไปเอง
สำหรับข้อความ/ข้อมูลสำหรับแต่ละภาษาแต่ละประเทศจะเก็บเป็นก้อนๆ เอาไว้ เรียกว่า locale
การจัดเตรียมข้อมูล locale พวกนี้เรียกว่า localization ซึ่งมีทั้งการแปลข้อความ และการเตรียมข้อมูลที่เจาะจงกับประเทศ/เขตการปกครอง/วัฒนธรรม
(ตัวย่อ i18n และ L10n มาจากอักษรแรกสุด+จำนวนตัวอักษรระหว่างอักษรแรกสุดกับอักษรท้ายสุด+อักษรท้ายสุด ใช้ i ตัวเล็ก และ L ตัวใหญ่ เพื่อให้เห็นแตกต่างจากเลขหนึ่ง 1)
ข้อมูลจำเพาะท้องถิ่น (locale)
ข้อความที่เจาะจงกับแอปในภาษานั้นๆ ก็ต้องแปลเอา ซึ่งมีเครื่องมือให้ช่วยแปลผ่านเว็บหลายตัว ตัวที่นิยมกันมากคือ Transifex (ใช้ฟรีสำหรับโครงการโอเพนซอร์ส) หรือจะใช้โปรแกรมอื่นๆ ก็มี โดยมาตรฐานการเก็บข้อความอันหนึ่งก็คือ gettext
ส่วนข้อมูลที่เป็นพื้นฐานสำหรับแต่ละภาษาแต่ละประเทศ ที่ไม่ขึ้นกับแอป มีคนทำเอาไว้แล้วที่โครงการ Unicode Common Locale Data Repository (CLDR)
เฟรมเวิร์กเกือบทั้งหมดรองรับการดึงข้อมูลจาก CLDR นี้ (และเราไม่ควรคิดใช้อะไรที่ต่างไปจาก CLDR ถ้าไม่ชัวร์จริงๆ ว่าคิดดีแล้ว)
ชื่อเรียก locale มีมาตรฐานกำหนดวิธีเรียกไว้ อยู่ในรูปแบบ:
- รหัสภาษาตัวพิมพ์เล็ก_รหัสประเทศตัวพิมพ์ใหญ่
- รหัสภาษาตัวพิมพ์เล็ก-รหัสประเทศตัวพิมพ์ใหญ่
เช่น th_TH คือภาษาไทยที่ใช้ในประเทศไทย, en_GB คือภาษาอังกฤษที่ใช้ในสหราชอาณาจักร, en_MY ภาษาอังกฤษที่ใช้ในมาเลเซีย, my_MM “ภาษาเมียนมาร์” ที่ใช้ในประเทศเมียนมาร์
รหัสภาษาและรหัสประเทศ โดยทั่วไปแล้วจะใช้ตามมาตรฐาน ISO ซึ่งจะมีทั้งแบบ 2 ตัวอักษร และแบบ 3 ตัวอักษร — โปรดสังเกตว่า รหัสภาษาและรหัสประเทศอาจจะแตกต่างกัน เช่น ภาษาญี่ปุ่นคือ ja ส่วนประเทศญี่ปุ่นคือ JP, หรือ MY ถ้าเป็นประเทศคือมาเลเซีย แต่ถ้าภาษา my คือ “ภาษาในเมียนมาร์”
บางทีเราจะเห็นชื่อ locale ในรูปแบบ รหัสภาษา_รหัสประเทศ_รหัสประเทศ อันนี้ต้องไปอ่านเอกสารของเฟรมเวิร์กนั้นๆ อีกทีว่าหมายความว่าอะไร เพราะมันไม่ใช่มาตรฐาน
เช่น th_TH_TH ใน Java จะหมายถึง ภาษาไทย, ในประเทศไทย, และใช้เลขไทยด้วย หรือ ja_JP_JP จะหมายถึง ภาษาญี่ปุ่น, ในประเทศญี่ปุ่น, และใช้การนับปีปฎิทินแบบญี่ปุ่น (Imperial calendar)
(ภาษาบางภาษาไม่มีโค้ดแบบ 2 ตัวอักษร แต่มีโค้ดแบบ 3 ตัวอักษร เช่น bur คือภาษาพม่า)
การทำงานของโค้ดที่ถูก internationalized แล้ว
ในการทำงานของโค้ด หลังจากโค้ดทราบภาษา/ประเทศของผู้ใช้ (จากที่ผู้ใช้ตั้งค่าเอง หรือจากการ detect/เดา หรือใช้ค่าจากระบบปฏิบัติการ) ตัวโค้ดก็จะไปดึงข้อมูลที่ตรงกันมาใช้ เพื่อกำหนดการแสดงผลหรือประมวลผล
เช่นถ้าทราบว่าเป็นผู้ใช้ภาษาอังกฤษ (en) ที่อยู่ในประเทศไทย (TH) ก็จะโหลด locale en_TH ขึ้นมาใช้ ซึ่งในการทำงานก็เป็นไปได้ว่า หน้าจอจะแสดงเป็นภาษาอังกฤษ แต่วันหยุดต่างๆ ใช้ตามปฏิทินของไทย
ส่วนข้อความที่แสดงผล (บนหน้าเว็บหรือทางอื่น) ตัวเฟรมเวิร์กจะกำหนดวิธีการแยกตัวโค้ดกับข้อความออกจากกัน ทำให้เราจัดการกับส่วนข้อความได้สะดวกขึ้น
โค้ดสามารถโหลดข้อมูล locale ได้จากทั้งฐานข้อมูล ใน string array ใน JSON หรือในแฟ้มต่างหาก อันนี้ก็ต้องไปตัดสินใจกันว่าทำงานแบบไหนสะดวกกว่า
i18n Library / Framework
ไลบรารี/เฟรมเวิร์กสำหรับ JavaScript ที่พบตอนนี้มีดังนี้
- FormatJS จาก Yahoo ใช้ร่วมกับ React และไลบรารีอื่นๆ ได้ https://formatjs.io
- Globalize จาก jQuery (Twitter ใช้ตัวนี้) https://github.com/globalizejs/globalize
- Polyglot จาก Airbnb http://airbnb.io/polyglot.js/
- jquery.i18n จาก MediaWiki https://github.com/wikimedia/jquery.i18n/
- i18next ตัวนี้เชื่อมกับเว็บช่วยแปลด้วย https://github.com/i18next/i18next/
มีคนทำตารางเปรียบเทียบไว้ https://github.com/rxaviers/javascript-globalization/blob/master/README.md
สำหรับ PHP มีคนแนะนำวิธีต่างๆ ไว้ https://lingohub.com/blog/2013/06/php-internationalization-i18n-mechanisms-tutorial/
สำหรับ Ruby on Rails มีตัวนี้อีกตัว https://github.com/fnando/i18n-js คุณ Vittayasak Rujivorakul แนะนำมา
จบดื้อๆ แค่นี้ มีอะไรไปคุยกันได้ในเฟซบุ๊กกรุ๊ป สมาคมโปรแกรมเมอร์ไทย ครับ https://www.facebook.com/groups/ThaiPGAssociateSociety/