ICU MessageFormat Translator: ทดสอบ plural และ select หลายภาษาก่อนส่งงานจริง
ICU MessageFormat Translator เครื่องมือฟรีในเบราว์เซอร์สำหรับเขียน ICU MessageFormat แบบ plural และ select พร้อม preview ผลลัพธ์ของ locale en, th, ar และ ru ด้วย plural rules จริง และตรวจจับ syntax error ได้ทันที
Table of Contents
นักพัฒนาเกือบทุกคนเคยส่งข้อความแบบ "You have 1 unread messages" ออกไปสักครั้ง ปัญหาไม่ใช่ความไม่รอบคอบ แต่ plural rules ของแต่ละภาษาไม่เหมือนกันเลย ภาษาอังกฤษใช้ 2 รูปแบบ ภาษารัสเซียใช้ 4 ส่วนภาษาอารบิกใช้ถึง 6 แบบ ICU MessageFormat Translator ช่วยให้คุณเขียน ICU MessageFormat ทั้งแบบ plural และ select ดู preview ผลลัพธ์ที่จัดรูปแบบแล้วของแต่ละ locale และตรวจจับ syntax error ได้ทันที ก่อนที่ข้อความเหล่านี้จะถึงมือผู้ใช้จริง
เรื่องนี้สำคัญเพราะ ICU MessageFormat เป็นมาตรฐาน de facto สำหรับข้อความที่ต้องแปลหลายภาษา React Intl, FormatJS, vue-i18n, Angular และ MessageFormat ของ Java ล้วนใช้รูปแบบนี้ แต่ syntax ของมันพลาดง่ายมาก แค่วงเล็บปีกกาที่ปิดไม่ครบ ลืม category other ที่จำเป็น หรือวางเครื่องหมาย # ผิด branch ก็ทำให้ build พังหรือแสดง placeholder ดิบ ๆ ให้ผู้ใช้เห็นได้
บทความนี้จะพาไปดูว่าเครื่องมือนี้ทำอะไรได้บ้าง plural categories ทำงานอย่างไรในแต่ละ locale เช่น en, th, ar และ ru และจะนำเครื่องมือนี้ไปใช้ใน workflow การ localize ของทีมได้ตรงไหนบ้าง
ทำไมต้องใช้ ICU MessageFormat Translator?
- Plural rules ต่างกันในแต่ละภาษา ภาษาอังกฤษถือว่า 0 เป็น other ภาษารัสเซียแยก one ออกเป็น one, few, many ส่วนภาษาอารบิกใช้ครบทั้ง 6 categories ของ CLDR ข้อความที่อ่านรู้เรื่องที่ count 1 อาจเพี้ยนสนิทที่ count 11
- ใช้ CLDR plural rules จริง ไม่ใช่การเดา preview คำนวณ plural category จริงของแต่ละ locale ตามค่าที่คุณกรอก สิ่งที่คุณเห็นสำหรับ ar หรือ ru คือสิ่งเดียวกับที่ผู้ใช้จะได้เห็นในแอป
- ตรวจ syntax ได้ทันที ลืมวงเล็บปิดหรือลืม clause other ที่บังคับไว้ เครื่องมือจะ flag error ให้เห็นทันที ไม่ต้อง build ไม่ต้อง recompile
- ดู preview หลาย locale เคียงข้างกัน เทียบผลลัพธ์ของ en, th, ar และ ru จากข้อความและค่า input เดียวกันในหน้าจอเดียว ทำให้ category ที่ไม่คาดคิดหลุดสายตาไม่ได้
- รันทั้งหมดในเบราว์เซอร์ ข้อความที่ยังไม่เปิดตัวไม่เคยออกจากเครื่องคุณ ไม่มีการอัปโหลด ไม่ต้องสมัครบัญชี ไม่มีการเรียกเซิร์ฟเวอร์
- ไม่ต้องตั้งค่าอะไรเลย ไม่ต้อง npm install ไม่ต้องแก้ไฟล์ config เปิดหน้าเว็บ วาง message แล้วเริ่มทดสอบได้ทันที
ฟีเจอร์หลักของเครื่องมือ
| ฟีเจอร์ | ทำอะไรได้ |
|---|---|
| Message editor | เขียน ICU MessageFormat ทั้งแบบ plural และ select ได้โดยตรงในเบราว์เซอร์ |
| Locale preview | เห็นผลลัพธ์ที่จัดรูปแบบแล้วของแต่ละ locale ทั้ง en, th, ar และ ru ด้วย CLDR plural rules จริง |
| Syntax checker | ตรวจจับ syntax error ได้ทันทีขณะพิมพ์หรือวางข้อความ |
| ตัวควบคุม count และ select | สลับค่า count หรือ select เพื่อดูทุก branch ของ message เรนเดอร์ออกมา |
| ทำงานฝั่ง client | ทุกอย่างรันในเบราว์เซอร์ ข้อความส่วนตัวของทีมจึงไม่หลุดออกไปไหน |
จุดที่น่าสนใจมีสองอย่าง หนึ่ง preview ของ plural ไม่ได้แค่แทนตัวเลขลงไปเฉย ๆ แต่คำนวณ CLDR category จริง เช่น one, few, many, other ของแต่ละค่าในแต่ละ locale ซึ่งตรงกับพฤติกรรมของ i18n library ใน production พอดี สอง syntax checker ทำงานทุกครั้งที่พิมพ์ วงจร feedback จึงสั้นกว่าการ build แล้วรีเฟรชหลายเท่า และเพราะทุกอย่างรันฝั่ง client คุณจึงทดสอบ copy ลับ ๆ ของผลิตภัณฑ์ได้โดยไม่ต้องกังวลเรื่องความปลอดภัย
วิธีใช้งาน ICU MessageFormat Translator
- เขียน message ของคุณ วาง key จากไฟล์ translation ที่มีอยู่ หรือเริ่มใหม่ด้วยข้อความอย่าง {count, plural, =0 {No unread messages} one {You have # unread message} other {You have # unread messages}}
- เลือก locale เลือกภาษาที่คุณปล่อยจริง เช่น en, th, ar และ ru เพื่อให้ preview สะท้อนกลุ่มผู้ใช้ของคุณอย่างแท้จริง
- สลับค่า count และ select ไล่ค่า 0, 1, 2, 5, 11 และ 100 แล้วสลับค่า select เช่น male, female, other เพื่อ exercise ทุก branch ของ message
- อ่าน preview แต่ละ locale จะเรนเดอร์ข้อความสุดท้ายตาม input ปัจจุบัน ให้คุณเช็คถ้อยคำ ช่องว่าง และตำแหน่งตัวเลขในบริบทจริง
- แก้ syntax error ทันที ถ้า checker ชี้ปัญหา เช่น วงเล็บไม่ปิดหรือขาด clause other ให้แก้แล้วยืนยันว่าทุก preview เรนเดอร์เรียบร้อย ก่อน copy กลับเข้าไฟล์ของโปรเจกต์
Plural ไม่ได้มีแค่ singular กับ plural เท่านั้น
หัวใจของ ICU MessageFormat คือ argument syntax ซึ่งเป็น placeholder ในวงเล็บปีกกาที่ระบุชื่อตัวแปร ประเภท และตัวเลือกของมัน plural argument มีรูปแบบ {count, plural, ...} ส่วน select argument หน้าตาเป็น {gender, select, male {...} female {...} other {...}}
CLDR กำหนด plural categories ไว้ 6 แบบ ได้แก่ zero, one, two, few, many และ other ภาษาอารบิกใช้ครบทั้ง 6 เพราะไวยากรณ์แยกกรณี zero, one, two, จำนวน 3–10 และ 11–99 ออกจากกัน ส่วน 100 ขึ้นไปอยู่อีกกลุ่มหนึ่ง ภาษาอังกฤษใช้แค่ one กับ other ภาษารัสเซียใช้ one, few, many, other และกฎของมันไม่เป็นธรรมชาติเท่าไร เลข 1, 21 และ 71 เป็น one แต่ 11 เป็น many ขณะที่ 22 กลับเป็น few นี่คือเหตุผลที่ความคิดแบบ "เอกพจน์กับพหูพจน์" ล่มทันทีเมื่อคุณเพิ่มภาษาที่สองเข้ามาในแอป
select argument ใช้จัดการ grammatical gender และทางเลือกแบบตายตัวอื่น ๆ ภาษาอย่างฝรั่งเศส เยอรมัน รัสเซีย และอารบิกผันคำคุณศัพท์หรือคำกริยาตามเพศของผู้ใช้ คำทักทายอย่าง {gender, select, male {...} female {...} other {...}} จึงหลีกเลี่ยงไม่ได้เวลาเขียน copy ให้ฟังเป็นธรรมชาติ
ภาษาไทยเป็นตัวอย่างตรงข้ามที่น่าสนใจ ไทยไม่ผันนามเป็นจำนวน ทุก count จึง map ไปที่ category other เท่านั้น เวลา preview ด้วย th คุณจะเห็นผลลัพธ์เหมือนกันทุกค่า count ซึ่งยืนยันว่าข้อความไทยของคุณไม่ต้องมี plural branches เลย แต่ภาษาต้นทางอย่างอังกฤษก็ยังต้องทำงานถูกต้องอยู่ดี
รายละเอียด syntax ที่คนพลาดบ่อยมีสองจุด ใน plural branch เครื่องหมาย # เปล่า ๆ คือชื่อย่อของตัวเลขของ argument ทำให้ You have # unread messages แทรก count ได้โดยไม่ต้องเขียน placeholder ซ้ำ ส่วนวงเล็บปีกกาและเครื่องหมาย # แบบตัวอักษรต้อง escape ด้วย apostrophe คือ '{', '}' และ '#' ถ้าลืม escape parser จะ error หรือกลืนเครื่องหมายวรรคตอนของคุณไปทั้งดื้อ ๆ
สรุปคือ ให้ทดสอบทุก category ที่ locale เป้าหมายสร้างได้ก่อนส่งงานเสมอ ข้อความที่เช็คแค่ค่า 0 กับ 1 ในภาษาอังกฤษยังพังได้ที่ 22 ในภาษารัสเซีย หรือที่ 15 ในภาษาอารบิก
กรณีการใช้งานจริง
ตรวจความแข็งแรงของไฟล์ translation
ก่อน release ให้เอา key ที่ซับซ้อนที่สุด เช่น plural ซ้อน select มาวางในเครื่องมือ แล้วไล่ค่า count ครบทั้งสี่ locale การพบว่าข้อความอารบิกของคุณขาด branch many ใช้เวลาแค่ 30 วินาที ถ้าไม่เช็คต้องรอให้ user มารายงานเอง
รีวิวข้อความจากนักแปลก่อน merge
เมื่อนักแปลส่งไฟล์กลับมา reviewer ตรวจได้ว่าข้อความที่แก้ compile ผ่านและเรนเดอร์ได้จริง โดยไม่ต้อารันแอปขึ้นมา วงเล็บที่หายไปในไฟล์ JSON สี่พันบรรทัดมองไม่เห็นใน diff ของ pull request แต่โชว์ชัดเจนใน preview ทันที
เขียนข้อความ notification หลายภาษา
อีเมล push notification และ template SMS มักแทรกตัวเลขอยู่เสมอ เช่น 3 tasks due หรือ 1 new follower การ preview ข้อความจริงของแต่ละ locale ช่วยจับกรณีที่แปลก ๆ เช่น count ภาษารัสเซียที่บังคับให้เปลี่ยนรูปกริยา ก่อนที่ template จะขึ้นใช้งานจริง
ใช้สอนแนวคิด i18n
กำลังแนะนำ ICU MessageFormat ให้เพื่อนร่วมทีมรู้จักอยู่ใช่ไหม เครื่องมือนี้ใช้เป็น sandbox ได้เลย พิมพ์ข้อความที่ผิด ดู error โผล่มา แก้มัน แล้วเทียบผลลัพธ์ข้าม locale ไม่มีวิธีไหนสร้างความเข้าใจเรื่อง categories และ escape ได้เร็วกว่านี้อีกแล้ว
แนวทางปฏิบัติที่ดีที่สุด
- ทดสอบทุก plural category ไล่ count อย่าง 0, 1, 2, 5, 11, 21 และ 100 ให้ครบทุก locale อย่างเชื่อว่าพฤติกรรมภาษาอังกฤษจะต่อยอดไปเองได้
- อย่าแบ่งประโยคข้าม key เก็บทั้งประโยคไว้ใน ICU message เดียว เพื่อให้ logic ของ plural และ select สมเหตุสมผลในทุกภาษา
- preview ar และ ru เสมอ สอง locale นี้มี category แปลก ๆ แน่นอน จึงจับข้อความที่เขียนด้วยสมมติฐานแบบอังกฤษล้วนได้ดีที่สุด
- ตั้งชื่อ placeholder ให้มีความหมาย ใช้ unreadCount ไม่ใช่ n เพื่อให้นักแปลเข้าใจบริบทของประโยคที่กำลังแปลอยู่
- ใส่ branch other ไว้เสมอ เป็น category ที่บังคับใน ICU และทำหน้าที่เป็นตาข่ายนิรภัยสำหรับค่าที่คุณไม่เคยคาดถึง
- เช็คข้อความซ้ำหลังนักแปลแก้ การแปลใหม่ทำให้เกิด syntax error ได้ง่ายพอ ๆ กับการแก้โค้ดเลยทีเดียว
พร้อมเลิกเดาว่าข้อความของคุณเรนเดอร์ออกมาเป็นอย่างไรในภาษาอื่นแล้วหรือยัง เปิด ICU MessageFormat Translator วาง key จริงจากโปรเจกต์ของคุณ แล้ว preview ทุก plural category ของ en, th, ar และ ru เสร็จภายในไม่กี่วินาที
เครื่องมือที่เกี่ยวข้องที่คุณอาจสนใจ:
- JSON Formatter — จัดรูปแบบ ตรวจสอบ และดูไฟล์ translation ที่เก็บ ICU messages ของคุณ
- Timezone Converter — จัดตารางและตรวจสอบ timestamp ของ release หลายภาษาให้ตรงเวลา
- Regex Tester — สร้างและ debug validation pattern ที่ทำงานร่วมกับข้อความที่แปลแล้ว
ขอให้สนุกกับการ localize ครับ
คำถามที่พบบ่อย
ถ: ICU MessageFormat คืออะไร? ตอบ: เป็นรูปแบบข้อความจากโปรเจกต์ ICU ของ Unicode สำหรับจัดรูปแบบข้อความที่รองรับหลาย locale รองรับทั้ง placeholder, plural, select และการจัดรูปแบบตัวเลขกับวันที่ ถูกใช้โดย React Intl, FormatJS, Angular, vue-i18n และ i18n library อีกมากมาย
ถ: เครื่องมือส่งข้อความของฉันขึ้นเซิร์ฟเวอร์ไหม? ตอบ: ไม่ ICU MessageFormat Translator ทำงานทั้งหมดในเบราว์เซอร์ ข้อความของคุณ รวมถึง copy ของผลิตภัณฑ์ที่ยังไม่เปิดตัว จึงไม่เคยออกจากเครื่องของคุณเลย
ถ: ทำไมข้อความของฉันพังในภาษาอารบิกแต่ไม่พังในภาษาอังกฤษ? ตอบ: อารบิกใช้ครบทั้ง 6 CLDR plural categories (zero, one, two, few, many, other) ถ้าข้อความของคุณนิยามแค่ category แบบภาษาอังกฤษ count อย่าง 15 หรือ 100 ในภาษาอารบิกจะหาข้อความไม่เจอหรือเกิด runtime error ได้
ถ: ICU MessageFormat ยังมีประโยชน์กับภาษาไทยอยู่ไหม? ตอบ: มีครับ ไทยไม่มีการผัน plural ทุก count จึง map ไปที่ category other เท่านั้น เครื่องมือยืนยันให้ว่าข้อความไทยของคุณเรนเดอร์เหมือนกันทุก count และ placeholder กับการ escape ถูกต้องครบถ้วน