กระต่ายในพงหญ้า คาโอโมจิกับอักษรไทย

มองเผิน ๆ เหมือนกระต่ายตัวเล็กกำลังจ้องเราอยู่ แต่ Unicode ไม่ได้ลงทะเบียนชุดนี้เป็นอีโมจิกระต่าย ฐานของมันคือ U+AA94…

หาสิ่งผิดปกติ
วิธีใช้เครื่องมืออ่าน

ฟังจะอ่านบทความออกเสียง อ่านเร็วแสดงวลีทีละช่วงตามความเร็วที่เลือก ฝึกภาษาใช้เปรียบเทียบบทความฉบับแปลที่มีอยู่ บันทึกจะเก็บบุ๊กมาร์กในเบราว์เซอร์นี้ และเปิดอีกครั้งได้จากรายการที่บันทึกในเครื่องเล่น อ่านแบบเกมทุบอิฐจะเปลี่ยนตัวอักษรในบทความเป็นก้อนอิฐให้ทุบเล่น

แชร์บทความนี้

แชร์บทความนี้

โฆษณา
โฆษณา

1. สรุปใน 5 วินาที: มองเห็นเป็นกระต่ายหนึ่งตัว แต่ข้างในคือโค้ดพอยต์สามตัว

ตัวปัญหาคือนี่:

ꪔ̤̮

มองเผิน ๆ เหมือนกระต่ายตัวเล็กกำลังจ้องเราอยู่ แต่ Unicode ไม่ได้ลงทะเบียนชุดนี้เป็นอีโมจิกระต่าย ฐานของมันคือ U+AA94 TAI VIET LETTER LOW TO แล้วตามด้วย U+0324 COMBINING DIAERESIS BELOW และ U+032E COMBINING BREVE BELOW.[1][2]

ภายนอก: สัตว์ตัวจิ๋วน่ารัก
ภายใน: อักษร Tai Viet + เครื่องหมายประกอบ + เครื่องหมายประกอบอีกตัว

หน้าตาเป็นมาสคอต แต่เอกสารภายในเหมือนระบบเก่าอายุยี่สิบปี

2. สรุปใน 30 วินาที: พอเอาไปใส่ใน “พงหญ้า” มันก็ดูเหมือนอาศัยอยู่ตรงนั้นจริง ๆ

จุดเริ่มต้นเป็นเพียงคาโอโมจิตกแต่ง:

- ̗̀ ꪔ̤̥ꪔ̤̮ꪔ̤̫ ̖́-

จากนั้นลองเอา “กระต่าย” ไปแทรกในอักษรเมียนมา:

မြန်မာမြန်မာမြန်မာ ꪔ̤̮ မြန်မာမြန်မာ

สำหรับคนที่อ่านอักษรนั้นไม่ออก รูปทรงกลม ๆ ที่เรียงแน่นอาจถูกสมองมองเป็นพื้นผิวคล้ายพุ่มไม้ แล้วหน้ากระต่ายก็เหมือนโผล่ออกมาจากกลางพง

พอใส่ในข้อความภาษาไทย เอฟเฟกต์ยิ่งชัด:

ภาษาไทยꪔ̤̮ภาษาไทย

ปฏิกิริยาแรกกลายเป็น “เดี๋ยวนะ… ตรงนั้นมีกระต่ายหรือเปล่า?”

ดังนั้นการทดลองที่ “เป็นวิทยาศาสตร์มาก” ขั้นต่อไปก็คือใส่สิบตัว

ภาษาไทยꪔ̤̮ภาษาꪔ̤̥ไทยภาษาꪔ̤̫ไทยꪔ̤̮กำลังꪔ̤̥เขียนอยู่ꪔ̤̫ภาษาไทยꪔ̤̮ภาษาꪔ̤̥ไทยภาษาꪔ̤̫ไทยꪔ̤̮

ถึงตรงนี้ไม่ใช่การอ่านแล้ว เป็นการสำรวจประชากรสัตว์ป่า

3. “กระต่าย” ตัวนี้ประกอบด้วยอะไรจริง ๆ

หน้าตา โค้ดพอยต์
ꪔ̤̥ U+AA94 + U+0324 + U+0325
ꪔ̤̮ U+AA94 + U+0324 + U+032E
ꪔ̤̫ U+AA94 + U+0324 + U+032B

U+AA94 เป็นพยัญชนะจริงในอักษร Tai Viet.[1] ส่วนเครื่องหมายด้านล่างเป็น combining marks ของ Unicode ที่มีรหัสและชื่อของตัวเอง.[2]

Unicode ไม่ได้ซ่อนกระต่ายไว้เป็นมุกลับ สมองมนุษย์ต่างหากที่มองเห็น “หน้า” จากการเรียงตัวของอักขระที่ถูกต้องตามระบบ

วัฒนธรรมคาโอโมจิเห็นช่องว่างนี้แล้วก็จัดให้ทันที

4. ทำไมพอแทรกในภาษาไทยแล้วดูพรางตัวได้แรงมาก

นี่ไม่ใช่การบอกว่าอักษรไทย “แปลก” แต่เป็นมุกจากมุมมองของคนที่อ่านอักษรไทยไม่ออก

ภาษาไทยมีสระและวรรณยุกต์ที่สามารถปรากฏเหนือ ใต้ หน้า หรือหลังพยัญชนะได้ และข้อความภาษาไทยทั่วไปไม่ได้เว้นวรรคทุกคำแบบภาษาอังกฤษ Unicode Line Breaking Algorithm จึงจัดอักษรไทยไว้ในกลุ่มที่ต้องอาศัยการวิเคราะห์ตามภาษาและบริบทเพื่อหาจุดตัดบรรทัดที่เหมาะสม.[4]

จากนั้นเราเอา ꪔ̤̮ ซึ่งตัวมันเองก็มีเครื่องหมายประกอบสองตัวอยู่ใต้ฐาน Tai Viet ไปแทรกตรงกลาง

คนที่อ่านภาษาไทยได้จะเห็นทันทีว่ามีอักขระจากระบบอื่นปะปนอยู่ แต่สำหรับคนที่อ่านไม่ออก เส้นโค้งกับเครื่องหมายบนล่างอาจถูกมองเป็น “พื้นผิว” ต่อเนื่อง ทำให้หน้ากระต่ายพรางตัวโดยบังเอิญ

ภาษาไทยꪔ̤̮ภาษาไทย

แปลแบบสายตาได้ประมาณว่า: หญ้า หญ้า หญ้า… เดี๋ยว เมื่อกี้อะไรสบตาเรา?

5. อักษรเมียนมา เขมร มาลายาลัม และสิงหลก็เล่นมุกนี้ได้

เมียนมา:

မြန်မာမြန်မာ ꪔ̤̮ မြန်မာမြန်မာ

เขมร:

ខ្មែរខ្មែរអក្សរ ꪔ̤̮ ខ្មែរខ្មែរ

มาลายาลัม:

മലയാളം മലയാളം ꪔ̤̮ മലയാളം

สิงหล:

සිංහල භාෂාව ꪔ̤̮ සිංහල

ไทย:

ภาษาไทยกำลังเขียนอยู่ ꪔ̤̮ ภาษาไทย

การจัดอันดับว่า “อักษรไหนซ่อนกระต่ายได้ดีที่สุด” เป็นเรื่องส่วนตัวล้วน ๆ อักษรเหล่านี้เป็นระบบการเขียนจริงที่มีผู้ใช้จริง ไม่ใช่ลวดลายตกแต่ง มุกเกิดจากสมองของคนที่ไม่คุ้นเคยกับอักษรนั้นมองรูปทรงเป็นพื้นผิวก่อน แล้วค่อยเจอหน้ากระต่ายที่แทรกอยู่

แต่ถ้าจัดการแข่งขันที่ไม่มีความจำเป็นที่สุดในโลก ภาษาไทยก็น่าจะเป็นตัวเต็ง

6. พอผ่านระบบแปลแล้วข้อความเคยเพี้ยนจริง แต่ยังโทษ Unicode normalization อย่างเดียวไม่ได้

หลังจากเอาเวอร์ชันสิบกระต่ายผ่านกระบวนการแปล เคยเห็นผลลัพธ์ที่มีช่องว่างผิดธรรมชาติประมาณนี้:

ภาษาไทยꪔ̤̮ภาษาꪔ̤̥ไทยภ าษาꪔ̤̫ไทยꪔ̤̮กำลังꪔ̤̥เข ียนอยู่...

เรียกมันว่า edge case ของการประมวลผล Unicode ได้ แต่ถ้าบอกว่า “Unicode normalization เป็นคนแทรกช่องว่าง” เลย ก็เร็วเกินหลักฐาน

Unicode normalization กำหนดวิธีแยก เรียงตาม canonical order และประกอบกลับลำดับอักขระที่มีความหมายเทียบเท่ากัน.[5] ส่วนระบบแปลอาจมีขั้นตอนอื่นอีกมาก เช่น การแบ่งประโยค การหาขอบเขตคำ tokenization การจัดการอักขระที่ไม่รู้จัก การบันทึกข้อมูล font fallback การจัดหน้า และการแปลงระหว่างคัดลอกกับวาง

ภาษาไทยและเมียนมาเองก็ต้องใช้การแบ่งข้อความที่พึ่งบริบทมากกว่าภาษาที่แบ่งคำด้วยช่องว่าง.[4] พอแทรก “อักขระฐานจากอีกระบบหนึ่ง + combining marks หลายตัว” ลงไป มันจึงเป็น stress test ที่น่าปวดหัวสำหรับ text pipeline ทั้งเส้น

ถ้าจะรู้ว่าจุดไหนเปลี่ยนจริง ต้องเทียบลำดับโค้ดพอยต์ทีละชั้น: input → storage → API request → ผลแปล → response parsing → rendering

กระต่ายน่ารัก รายงาน incident ไม่ได้น่ารักตาม

7. “หนึ่งตัวอักษร” ที่ตาเห็น ไม่จำเป็นต้องเท่ากับหนึ่ง Unicode code point

Unicode มีแนวคิด grapheme cluster เพื่อประมาณหน่วยที่ผู้ใช้รับรู้ว่าเป็น “หนึ่งอักขระ”.[3]

ตัวอักษรที่มีเครื่องหมายกำกับอาจถูกเก็บเป็นโค้ดพอยต์ที่ประกอบสำเร็จแล้วหนึ่งตัว หรือเป็นอักขระฐานตามด้วย combining marks หนึ่งหรือหลายตัวก็ได้ บนหน้าจออาจเห็นเป็นหน่วยเดียวเหมือนกัน

กระต่ายตัวนี้ก็มีหลายตัวตน:

  • ทางสายตา: กระต่าย 1 ตัว
  • ภายใน: 3 โค้ดพอยต์
  • ความยาวสตริง: ขึ้นกับโมเดลของภาษาโปรแกรมหรือ API
  • การเลื่อนเคอร์เซอร์: ควรเคารพหน่วยที่ผู้ใช้รับรู้
  • Backspace: อาจทำงานต่างกันตาม implementation
  • การค้นหาและเปรียบเทียบ: ขึ้นกับนโยบาย normalization
  • ฟอนต์: fallback และตำแหน่ง combining marks อาจเปลี่ยนรูปร่าง

สรุปว่าทะเบียนสัตว์ป่านับกันเป็นโค้ดพอยต์

8. เป็นมุกก็จริง แต่ดันเป็น Unicode test fixture ที่ดี

ꪔ̤̮ ใช้ทดสอบได้หลายอย่าง:

  1. UTF-8 round trip
  2. combining marks หายหรือไม่ตอน copy-paste
  3. การนับ code point กับ grapheme cluster
  4. เคอร์เซอร์และการลบ
  5. นโยบายเปรียบเทียบ NFC/NFD
  6. font fallback และตำแหน่งเครื่องหมาย
  7. การตัดบรรทัดเมื่อผสมกับไทย เมียนมา หรือเขมร
  8. translation API round trip
  9. search index
  10. การแสดงผลข้ามเบราว์เซอร์และมือถือ

แต่ไม่ควรเอาไปโปรยในข้อมูลจริงแบบไม่มีเหตุผล ควรแยกสตริงประหลาดไว้ใน test fixture และระบุลำดับโค้ดพอยต์ที่คาดหวังให้ชัด

อย่าปล่อยกระต่ายป่าเข้า production database

9. วิธีรับมือจริงสำหรับเว็บหลายภาษา

  • ใช้ UTF-8 ให้สม่ำเสมอ
  • กำหนดนโยบาย normalization ให้ชัดเจน เนื้อหาเว็บมักใช้ NFC แต่กรณีที่ต้องรักษาต้นฉบับต้องมีข้อยกเว้นที่ระบุไว้.[5]
  • แยกความหมายของ byte, code unit, code point และ grapheme cluster
  • ใส่ lang ให้ถูกต้อง และทดสอบฟอนต์กับ line-height ที่เหมาะสม
  • ทดสอบอักษรไทย เมียนมา เขมร และระบบอื่นที่ไม่สามารถจัดการได้ด้วยการ split ตามช่องว่างอย่างง่าย.[4]
  • อย่าแก้ข้อความที่ผู้เขียนสร้างเองแบบเงียบ ๆ ระหว่างนำเข้าคำแปล
  • QA ตำแหน่งเครื่องหมาย การตัดบรรทัด selection copy-paste search และ accessibility ไม่ใช่ดูแค่ว่ามี mojibake หรือไม่
  • ถ้าเพี้ยน ให้เทียบสตริงทีละ layer ก่อนสรุปว่า “Unicode พัง”

ส่วนใหญ่ Unicode ทำตามสเปกของมัน ปัญหามักเริ่มตอนซอฟต์แวร์แอบสมมติว่า “สิ่งที่เห็นเป็นหนึ่งตัว = ภายในเป็นหนึ่งหน่วยง่าย ๆ”

ตรงนั้นเองที่กระต่ายเดินออกมาจากพุ่ม

10. สรุป: สิ่งที่ซ่อนอยู่ในพงหญ้าคือการมองหารูปแบบของมนุษย์กับความลึกของ Unicode

เรื่องเริ่มจากคาโอโมจิน่ารัก:

ꪔ̤̮

พออยู่ในอักษรเมียนมาก็ดูเหมือนซ่อนในพุ่ม พออยู่ในภาษาไทยก็ดูเหมือนมีถิ่นอาศัยอยู่แล้ว ใส่สิบตัวก็กลายเป็นประชากร ส่งผ่านระบบแปลก็กลายเป็นบทเรียน debugging Unicode

ใต้เรื่องตลกมีบทเรียนจริง:

  • หนึ่งอักขระที่มองเห็นอาจประกอบด้วยหลายโค้ดพอยต์
  • combining marks ถูกวาดร่วมกับอักขระฐาน
  • บางระบบอักษรต้องใช้การแบ่งข้อความที่รู้ภาษา
  • normalization, segmentation, line breaking, font, translation และ rendering เป็นคนละ layer
  • หน้าจอที่ดูประหลาดเพียงอย่างเดียวบอกไม่ได้ว่า layer ไหนผิด

และหลังจากเห็นบรรทัดนี้เป็น “กระต่ายในพงหญ้า” ไปแล้วสักครั้ง:

ภาษาไทยꪔ̤̮ภาษาไทย

ก็ยากจะกลับไปมองแบบเดิม

ตั้งใจมาเรียน Unicode สุดท้ายกลับบ้านหลังยืนยันแหล่งอาศัยของกระต่ายเรียบร้อย


ลึกลงไปอีกนิด: เอา “วิธีรักษา Dopagaki” ไปทำเป็นคลิปสั้น สุดท้ายเหมือนกับดักกรง — ใช้โดปามีนปราบโดปามีนในพื้นที่ล่าของอัลกอริทึม

โฆษณาหนังสือในหัวข้อนี้

  • The Pragmatic Programmer (ฉบับภาษาอังกฤษ)

    Andy Hunt, Dave Thomas / Pragmatic Programmer / 1999

    หนังสือในด้าน การเขียนโปรแกรม ซึ่งเป็นสาขาของบทความนี้

บทความนี้มีลิงก์พันธมิตร (โฆษณา). เกี่ยวกับโฆษณา As an Amazon Associate I earn from qualifying purchases.

แชร์บทความนี้

หากบทความนี้มีประโยชน์ คุณสามารถสนับสนุนเว็บไซต์ได้ สนับสนุน

โฆษณา
โฆษณา
โฆษณา

อีกสักเรื่องไหม มีอะไรสนุก ๆ บ้าง

อ่านจบแล้วก็ลองต่อเลย: เรื่องใกล้เคียงไม่กี่เรื่อง และเรื่องที่ต่างไปเลยแต่สนุก

  1. ว่าที่แม่สามีจะ "ตัดสิน" ว่ายอมรับเราไหม แฟนพูดแค่ "แม่ก็แค่เป็นห่วง" สรุปใครมีสิทธิ์ตัดสินใจ และทำไมคำว่า "ต้องมีความคิดริเริ่ม" ทำให้คนเก่งลาออก
  2. Smash Ultimateทำไม Mythra ตีก่อนแล้วแพ้ Kazuya กับ K. Rool?
  3. ตี 5ร่างกายบอก “นอนได้แล้ว” แต่สมองบอก “ร้านยังเปิดครับ”
  4. ทำไม “Yohohoho” ของ Ado กลับมาฮิต? เพลง Binks' Sake ถูกรีมิกซ์จนมีคนเล่นด้วยเมโลเดียน

วันนี้อ่านเรื่องนี้

แต่ละบทความตอบคำถามที่ผู้อ่านบทความนี้มักสงสัยต่อ

ดูบทความทั้งหมดบทความเรื่อง เทคโนโลยี เพิ่มเติม

หาบทความอื่น

บทความทั้งหมด

Mendoi-chan

ผู้ดูแลเว็บไซต์

Mendoi-chan

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

โฆษณา

บทความล่าสุด

  1. 1ทำไม ChatGPT Plus เห็น Dots แต่ใช้งานไม่ได้? เรื่องตลกของป้ายชื่อกับประตูล็อก
  2. 2ท่าเต้นรัมเพิลสติลต์สกินมาจากหนังเก่าเรื่องไหน? ไม่มีหนังเรื่องนั้น
  3. 3เกมต่างโลกโยนภารกิจมาไม่หยุด แต่ฉันแค่อยากกลับบ้านให้เร็วที่สุด
  4. 42XKO เตรียมเพิ่ม Sett กับ Samira วันที่ 27 ต.ค. แต่จะเป็นตัวละครใหม่ชุดสุดท้ายจริงหรือ?
  5. 5ชนะชีวิตในเกม 1 in 8 Billion คืออะไร? อายุยืน เงินเยอะ หรือคนที่รัก
โฆษณา