ทำเว็บ ทำแอป ให้รองรับหลายภาษา หลากวัฒนธรรม

ไลบรารี/เฟรมเวิร์กสำหรับการทำให้แอป/เว็บไซต์รองรับหลายภาษา/วัฒนธรรม หรือที่เรียกว่า “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 ที่พบตอนนี้มีดังนี้

มีคนทำตารางเปรียบเทียบไว้ 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/

โพสต์(อาจจะ)ที่เกี่ยวข้อง

มากกว่าการแปล, localization คือการปรับเข้าถิ่น

ผมเริ่มงานแรกหลังเรียนจบตรี ในอุตสาหกรรมซอฟต์แวร์ (จริงๆ เริ่มก่อนจบน่าจะสามเดือนได้ ซึ่งงานนี่ก็เกือบทำให้ไม่จบ :p) งานที่ทำอยู่ในหมวด “software localization” หรือเรียกย่อๆ ว่า L10n (L ตามด้วยอักษรอีกสิบตัว ปิดท้ายด้วย n)

software localization ไม่ใช่แค่การแปลซอฟต์แวร์ให้ใช้ภาษาถิ่น แต่ต้องปรับให้เข้ากะท้องถิ่น (locale) ด้วย

เช่น มาตรฐานเข้ารหัสและจัดเก็บตัวอักษร (ยูนิโค้ด สมอ. ASCII JIS)

การจัดเรียงลำดับข้อมูล (เอาอะไรมาก่อนหลัง พยัญชนะ สระ วรรณยุกต์ ตัวไหนสำคัญกว่าตอนเรียง)

ระบบปฏิทิน (ศักราช การนับวันแรกของสัปดาห์ วิธีเรียกวัน การเขียนวันที่เอาวันหรือเดือนมาก่อน วันหยุดประจำปี เวลา 24 ชั่วโมงหรือ am/pm เขตเวลา ปรับเวลาออมแสงเมื่อใด)

ระบบจำนวนและระบบนับ (เลขไทย เลขอารบิค การออกเสียงจำนวน “211 -> สองร้อยสิบเอ็ด” การรันเลขรายการ “๑) ๑.๑) ๑.๑.ก)” เครื่องหมายบอกหลัก “1,000.00 vs 1.000,00”)

หน่วยชั่งตวงวัด (อิมพีเรียลหรือเมตริก ใช้กระดาษแบบ Letter หรือ A4) หน่วยเงิน (บาท-สตางค์ ดอลลาร์-เซนต์)

รูปแบบการเขียนชื่อ คำนำหน้า ที่อยู่ ไปรษณีย์ เลขหมายโทรศัพท์

เครื่องหมาย สัญลักษณ์พื้นฐาน สี (ถูก-ผิด ใช่-ไม่ใช่ O X / อัญประกาศเปิดปิด) และอีกมาก

บางเรื่องเป็นเรื่องที่สามารถทำได้เลย ไม่ต้องเข้าไปแก้ไขตัวโปรแกรม แต่บางเรื่องก็จำเป็นต้องไปปรับโปรแกรมให้มันรองรับเสียก่อน

เมื่อก่อนโปรแกรมจำนวนมากถูกออกแบบมาโดยไม่คำนึงถึงการทำตลาดในวัฒนธรรมอื่นๆ ทำให้ยากที่จะปรับ บางทีก็ต้องแงะงัด เสียเวลามากและไม่ยั่งยืน เพราะพอโปรแกรมออกเวอร์ชันใหม่ ก็ต้องมาแงะงัดกันอีกรอบ

การทำให้ซอฟต์แวร์สามารถทำ localization ได้สะดวก เรียกว่าการทำ internationalization หรือ i18n เป็นการเตรียมความพร้อมให้ซอฟต์แวร์ไม่ “taken for granted” เหมารวมไปว่าสิ่งคุ้นชินทางวัฒนธรรมของโปรแกรมเมอร์นั้น คนอื่นๆ ในโลกจะใช้แบบนั้นไปด้วย

โปรแกรมรุ่นใหม่ๆ ในช่วงสิบปีที่ผ่านมา ออกแบบมาโดยคำนึงถึงเรื่องนี้มากขึ้น ส่วนหนึ่งก็ต้องขอบคุณภาษาโปรแกรม เครื่องมือพัฒนา และระบบปฏิบัติการรุ่นใหม่ๆ ที่ทำให้การเขียนโปรแกรมแบบ i18n สะดวกขึ้น ซึ่งก็ทำให้ทำ L10n ได้ง่ายตามไปด้วย

ในเมืองไทย คนที่ทำเรื่องนี้มานานก็เช่น @theppitak @htk999 @untsamphan @pruet @nanusorn ทำมาตั้งแต่สมัยบุกเบิก ยังไม่มีมาตรฐานสากลเรื่องนี้มากนัก ต้องทำโครงสร้างพื้นฐานขึ้นเองเลย คนเหล่านี้จำนวนมากมีความสัมพันธ์ในทางหนึ่งทางใดกับ NECTEC

อีกรุ่นถัดมาก็เป็น @markpeak @veer66 @kengggg @pittaya ฯลฯ ที่ทำบนฐานของซอฟต์แวร์ที่ออกแบบเรื่อง i18n มาไว้ค่อนข้างดีแล้ว และมาตรฐานอุตสาหกรรมหลายอย่างในเรื่องนี้ก็นิ่งแล้ว

จริงๆ ไม่ต้องพูดถึงเรื่องซอฟต์แวร์อะไรให้ยุ่งยาก เฉพาะการแปลข้อความปกติ ในวิธีคิดแบบ L10n ก็ควรจะแปลแบบปรับเข้าถิ่น ให้สามารถสื่อความความหมายที่ต้องการไปสู่วัฒนธรรมนั้นๆ ได้ ไม่จำเป็นต้องแปลแบบตามอักษร

ภาพนี้เอามาจากเว็บไซต์ไมโครซอฟท์ ที่ชวนคนให้ไปใช้ SkyDrive อย่าใช้ Dropbox เลย

ในราคาเพียง $10/ปี ซึ่งอาจจะถูกกว่าค่าอาหารกลางวันอีกนะ

จะเห็นว่า เป็นการแปลแบบรักษาต้นฉบับไว้ดีมาก แต่มันไม่ลงตัวเท่าไหร่กับถิ่นไทย หน่วยเงินยังเป็นดอลลาร์ และพอแปลงตัวเลขมาเป็นบาทก็ร่วม 300 ซึ่งก็ไม่เมกเซนซ์กับราคาข้าวกลางวันในเมืองไทย (ที่สามร้อยบาทนี่คือค่าแรงขั้นต่ำ :p)

กะจะแค่แคปมาให้ดูเล่นๆ ดันเขียนซะยืดยาว ถือว่าแชร์กันละกัน

เรื่อง “taken for granted” เหมาว่าคนอื่นก็คงคิดเหมือนเรา ทำแบบเรานี่แหละ และเรียกร้องให้ผู้ใช้ปรับตัวให้เข้ากับ “ผลิตภัณฑ์” ที่เราออกแบบ เป็นเรื่องที่เห็นกันทั่วไป ไม่เฉพาะในวงการซอฟต์แวร์

—-
โพสต์ครั้งแรกที่เฟซบุ๊ก Art Bact’

Citrus Project – i18n framework for BSD

The Comprehensive I18N framework Towards Respectable UNIX Systems Project — Citrus Project

from its website …


Purpose:
To create for the existing BSD series of PC-UNIX (FreeBSD, NetBSD, OpenBSD, BSD/OS) the following things:

  1. Locale/iconv implementation to conform to ISO C/SUSV2
  2. Non-GPL gettext and POSIX NLS catalog implementation
  3. It is a goal to develop system standard multi-script encoding by internationalization of file name
  4. Design and implement multi-script framework.

For now, our goal is the same level of functionality as Solaris 7 supports.


m17n-enabled Mozilla

มีใครดูตัวนี้อยู่บ้างครับ? ผมยังไม่ได้ดูละเอียดๆ แต่เหมือนจะเน้นเรื่อง input และ output เป็นหลัก? (i.e. ไม่มีเรื่องตัดคำ)

เพิ่งรู้ว่าเค้าเอามาใส่ใน Mozilla แล้ว (มี patch สำหรับ Firefox 1.0PR แล้วด้วย)