คิดเงิน “ตามตัวอักษร” แฟร์ไหม?

เช็คอะไรนิดหน่อย ไปเจออันนี้ วิธีการคิดเงินของ Google Cloud Translation API ก็แฟร์ระดับหนึ่งนะ คือคิดตามจำนวนตัวอักษร (code point) แทนที่จะคิดตามปริมาณข้อมูลจริงๆ (byte)

Charged characters

To calculate usage, Google counts usage on a per character basis, even if a character is multiple bytes. Each character corresponds to a code point.

You are charged for all characters that you include in a Cloud Translation request, even untranslated characters. This includes, for example, whitespace characters. If you translate <p>こんにちは</p> to English, it counts as 12 characters for the purposes of billing.

Google also charges for empty queries. If you make a request without any content, Google charges one character for the request.

—-

คือในทางคอมพิวเตอร์ มาตรฐานตัวอักษรที่แพร่หลายในปัจจุบัน คือมาตราฐาน Unicode และวิธีการจัดเก็บตัวอักษรที่นิยมและเข้ากันได้กับแอปบนอินเทอร์เน็ตต่างๆ ก็คือ UTF-8 ซึ่งในตัวอักษรในแต่ละระบบการเขียนอาจใช้จำนวนไบต์ไม่เท่ากัน ตัวละตินที่ไม่มีเครื่องหมายประสม (อย่างที่ใช้ในภาษาอังกฤษ มาเลย์ อินโด) จะใช้เพียง 1 ไบต์ต่อ 1 ตัวอักษร (code point) ส่วนตัวอักษรไทยจะใช้ 3 ไบต์ต่อ 1 ตัวอักษร

จากการตัดสินใจในขั้นการออกแบบ มันเป็นไปได้ที่จะมีการเลือกปฏิบัติ มีความ “ไม่เท่าเทียม” หรือความ “ไม่ปลอดภัย” หรือความใดๆ ที่ถ้าเป็นไปได้ก็ไม่อยากให้มี ฝังอยู่ในระบบสถาปัตยกรรมของระบบ บางอย่างไม่ได้อยากให้มี แต่ด้วยข้อจำกัดของทรัพยากรที่มีจำกัดกว่าหรือสมมติฐานของบริบทการใช้งานในตอนที่ออกแบบ ก็เลยตัดสินใจว่าใช้แบบนี้ไปละกัน มันโอเคสำหรับตอนนั้น – แต่พอเวลาผ่านไป ย้อนกลับไปพิจารณา ก็อาจตัดสินใจอีกแบบได้ (จะมีโอกาสแก้ไขไหมก็อีกเรื่อง)

ตัวอย่างหนึ่งก็เช่นระบบอีเมลและ www ที่ไม่ได้มีการเข้ารหัสลับมาในระดับมาในโปรโตคอลแต่แรก ซึ่งก็อาจเป็นการตัดสินใจทางวิศวกรรมที่สมเหตุสมผลสำหรับบริบทการใช้งานขณะนั้น ที่เป็นการใช้งานระหว่างหน่วยงานที่เชื่อใจกันอยู่แล้ว และการจะเข้าสู่ระบบได้ต้องให้ผู้ดูแลระบบสร้างบัญชีให้ รู้ตัวตนกันแน่นอน ดังนั้นอาจจะไม่ต้องห่วงเรื่องดักฟังหรือการยืนยันตัวตนมาก ที่ต้องห่วงมากกว่าคือจะส่งข้อมูลยังไงให้เล็กให้เร็ว เพราะแบนด์วิธสมัยนั้นมันต่ำ ทางยังแคบ

แต่ต่อมาเมื่อสมมติฐานความปลอดภัยนั้นไม่เป็นจริงแล้ว หรือข้อจำกัดทางเทคโนโลยี/เศรษฐกิจนั้นได้คลายลงแล้ว ก็มีการคิดวิธีเข้ารหัสลับให้กับข้อมูลขึ้นมา โดยยังทำงานอยู่บนโปรโตคอลเดิม มีความเข้ากันได้กับระบบเก่าๆ (backward compatible)

การออกแบบคอมพิวเตอร์ดิจิทัลยุคแรก นอกจากจะมีแต่ตัวละตินแล้ว ยังไม่มีกระทั่งตัวอักษรพิมพ์เล็ก เพราะพื้นที่หน่วยความจำและจัดเก็บมีขนาดจำกัด และยังต้องกันที่สำหรับอักขระพิเศษเพื่อควมคุมเครื่องพิมพ์เข้าไปด้วย (จอภาพอาจไม่ใช่ส่วนแสดงผลหลักของระบบคอมพิวเตอร์หลายๆ ระบบในตอนนั้น และการแสดงผลกราฟิกที่แม่นยำที่สุด ก็คือพล็อตเตอร์ ที่เป็นแขนกลวาดรูปด้วยปากกา)

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

เมื่อระบบเหล่านี้ขยายใหญ่ขึ้น มีการนำไปใช้กับหลากหลายภาษาวัฒนธรรรมมากขึ้น มีผู้ใช้จำนวนมากขึ้น จากหลากหลายภูมิหลังขึ้น ใช้กับหลากหลายบริบทความปลอดภัยมากขึ้น สมมติฐานหลายๆ อย่างที่เคยใช้ได้ ก็เปลี่ยนไป

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

เช่น เดิมใช้ 7 บิตเพื่อแทนชุดตัวอักษร 128 ตัว ก็ขยายมาเป็น 8 บิต 16 บิต ฯลฯ โดยพยายามทำให้มันรองรับระบบเดิมอยู่ โดย 128 ตัวแรก ยังใช้ตัวอักษรชุดเดิมอยู่อะไรงี้ ซึ่งวิธีที่เก็บตัวอักษรที่ใช้บนอินเทอร์เน็ตส่วนใหญ่ตอนนี้ใช้วิธีนี้อยู่ ชื่อมาตรฐานคือ UTF-8

UTF-8 นี่เป็นวิธีการแปลงรหัสเพื่อบันทึกตัวอักษรแบบที่เรียกว่า “variable-width encoding” คือ ตัวอักษรแต่ละตัวอาจใช้จำนวนข้อมูล (คิดเป็นไบต์) ในการเก็บไม่เท่ากัน — พวกตัวอักษรละตินและสัญลักษณ์พื้นฐาน 128 ตัวแรก จะใช้ 1 ไบต์ ตัวละตินอื่นๆ เกือบทั้งหมดที่เหลือ (ซึ่งภาษาจำนวนมากในยุโรปใช้ รวมถึงภาษาอย่างเวียดนาม ก็ใช้ตัวเขียนเหล่านี้) รวมถึงตัวอักษรกรีก ฮีบรู อารบิก คอปติก พวกนี้ใช้ 2 ไบต์ ตัวอักษรที่เหลือเกือบทั้งหมดจะใช้ 3 ไบต์ ในกลุ่มนี้มีตัวอักษรจีน ญี่ปุ่น เกาหลี ไทย รวมอยู่ด้วย ส่วนพวก 4 ไบต์นี่จะเป็นตัวอักษรที่ไม่พบบ่อยนัก หรือเป็นส่วนขยาย/กรณีพิเศษของตัวอักษรบางตัว

วิธีคิดของคณะออกแบบ UTF-8 ก็คือ ตัวอักษรไหนมีแนวโน้มจะใช้บ่อย ใช้มาก ก็พยายามให้ใช้จำนวนไบต์น้อยๆ เพื่อที่ว่าในภาพรวมจะได้ประหยัดพื้นที่จัดเก็บ เว้นเสียว่าจะทำไม่ได้จริงๆ อย่างกลุ่มตัวอักษรจีน​ญี่ปุ่นเกาหลี (CJK) ที่จำนวนตัวอักษรมันเยอะ จะยัดลง 2 ไบต์ก็ไม่ไหว ก็ใช้ 3 ไบต์ไป

ซึ่งในแง่นี้ การให้ตัวอักษร ASCII ใช้เพียง 1 ไบต์ ก็เข้าใจได้มาก ๆ เพราะตัวอักษรในชุดนี้ถูกใช้เป็นคำสั่งและคำสำคัญต่างๆ ในโปรโตคอลการรับส่งข้อมูลและมาตรฐานข้อมูลอื่น ๆ ในระดับพื้นฐานของคอมพิวเตอร์ ถ้าเกิดตัวอักษรชุดนี้ใช้จำนวนไบต์เยอะ ทุกอย่างในระบบก็จะพองขึ้นทันที ซึ่งผลพลอยได้ก็คือ พวกภาษาที่ใช้ตัวอักษรที่อยู่ในกลุ่มตัวละติน (A-Z, a-z) ก็เลย “โชคดี” ไปด้วย (หรือมองอีกมุม ก็เป็นเพราะคนที่ใช้ภาษาที่ใช้อักษรละติน เป็นคนกำหนดมาตรฐานคอมพิวเตอร์ไง ผลที่ตามมาเลยเป็นแบบนี้)

อย่างไรก็ตาม ก็มีคำถามแหละ ว่าเอ๊ะ แล้วเอาเฉพาะชุดตัวที่ใช้บ่อยๆ ของตัวอักษรที่ตอนนี้ถูกจัดอยู่ในหมวด 3 ไบต์ (อย่าง CJK) ไปอยู่ใน 2 ไบต์ก็ได้รึเปล่า อย่าง ฮันกึลของเกาหลี หรือ คะนะของญี่ปุ่น พวกนี้ก็ไม่ได้เยอะมากแบ่งไปใส่ในชุด 2 ไบต์ได้ไหม แล้วพวกฮันจาหรือคันจิ (ตัวจีน) ค่อยใส่ในชุด 3 ไบต์ ไม่ต้องยกกันไปทั้งยวงก็ได้

หรืออย่างตัวอักษรไทย มันก็ไม่ได้เยอะอะไร รวมพยัญชนะ รูปสระ วรรณยุกต์ เครื่องหมายวรรคตอน ตัวเลขไทย มีประมาณ 80-90 ตัวได้ ไม่ได้เยอะมาก และคนใช้ตัวอักษรไทยก็ไม่ได้น้อย น่าจะมากกว่าคนใช้ภาษาคอปติกในชีวิตประจำวันแน่ ทำไมอักษรไทยถึงได้เป็น 3 ไบต์ และคอปติกได้ 2 ไบต์

คำว่า “บ่อย ๆ” นี่เอาอะไรวัด จากมุมของใคร หรืองานแบบไหน

แต่เอาล่ะ มาตรฐานมันก็กำหนดมาแบบนี้แล้ว ไปแก้อะไรไม่ได้ (จริงๆ ก็แก้ได้ แต่ต้องไปตามแก้ข้อมูลที่ถูกจัดเก็บไปแล้วทั้งหมด ก็ลำบากมากๆ อยู่) ก็เลยกลายเป็นว่ามีบางภาษา พอออกมาเป็นรูปตัวเขียน ต้องใช้พื้นที่ในการจัดเก็บมากกว่าภาษาอื่น เพราะต่อ 1 ตัวอักษร ใช้จำนวนไบต์มากกว่า

กลับไปประเด็นตั้งต้น ถ้าบริการไหนคิดค่าบริการตามจำนวนไบต์ (ขนาดพื้นที่จัดเก็บ/รับส่งข้อมูลจริงๆ) มันก็เป็นประเด็นได้ว่า ทำให้ผู้ใช้ภาษาบางภาษาหลีกเลี่ยงไม่ได้ที่จะต้องจ่ายแพงกว่าภาษาอื่น

วิธีการคิดค่าบริการตามจำนวนตัวอักษร แทนที่จะเป็นจำนวนไบต์ข้อมูลที่จะต้องใช้เก็บตัวอักษรนั้น ก็เลยถูกมองได้ว่าแฟร์ขึ้นมาอีกนิดนึง

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

หรือถ้าไปให้สุดๆ เฮ้ย บางภาษา 1 ตัวอักษร มันเก็บความหมาย อุ้มความหมายเอาไว้ได้เยอะกว่า 1 ตัวอักษรในอีกภาษา ภาษาญี่ปุ่นเขียน 1 ตัว 空 ภาษาไทยต้องเขียน 7 ตัว เพื่อจะได้ความหมายว่า ท้องฟ้า เท่ากัน แบบนี้คนไทยก็ต้องจ่ายแพงกว่าคนญี่ปุ่นรึเปล่า (แบบ 280 ตัวอักษรบนทวิตเตอร์ คนจีนแทบจะเขียนเรื่องสั้นได้แล้ว คนไทยแค่รายงานข่าวอาจจะไม่พอ) แบบนี้การคิดค่าบริการตามตัวอักษรก็ไม่แฟร์อยู่ดีปะ

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

ตราบใดที่การสร้างมันเกิดการกระบวนการตัดสินใจเลือก การเลือกปฏิบัติมันมีอยู่แน่ๆ ในผลงานทางวิศวกรรม

มันไม่จำเป็นต้องเป็นการเลือกปฏิบัติในทางลบ (ภาษากฎหมายระหว่างประเทศใช้คำว่า “การเลือกประติบัติ”) มันอาจเป็นทางบวกก็ได้ (จริงๆ การคำนึงถึงความถี่ในการใช้และพยายามให้ตัวอักษรที่พบบ่อย ใช้จำนวนไบต์น้อยๆ ก็เป็นการเลือกปฏิบัติที่พยายามจะให้เกิดผลบวกในภาพรวม ทำให้ในภาพรวมใช้พื้นที่จัดเก็บน้อยลง ส่งข้อมูลได้ไวขึ้น ประหยัดขึ้น)

และหลายครั้งก็ไม่ได้เป็นเรื่องตั้งใจให้เกิดการปฏิบัติที่แตกต่างกับกลุ่มคนแบบนั้นแต่แรก แต่อาจมาจากความไม่รู้ ไม่ได้อยู่ในความคิด-อันเนื่องมาจากการติดต่อข้ามวัฒนธรรมยังมีจำกัดในอดีต พอมารู้แล้วในตอนหลังจะให้รื้อทำใหม่หมดก็มีข้อจำกัด ก็เลยยังต้องใช้ของที่มีมาแต่เดิมผสมอยู่ด้วย รื้อหมดไม่ได้

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

เผยแพร่ครั้งแรก 7 เมษายน 2564 บนเฟซบุ๊ก

พอโพสต์เรื่องข้างต้นจบ ก็นึกถึงอีกประเด็นในสัปดาห์ก่อนหน้า ที่คนพูดถึงบทความ When Binary Code Won’t Accommodate Nonbinary People ซึ่งก็คิดๆ ไปก็น่าจะเป็นเรื่องของ encoding นี่อยู่เหมือนกัน เป็นการเอาการจัดประเภทฝังลงไปในระบบ

ถ้าได้อ่านในบทความนั้น คิดว่าหลักใหญ่ใจความประเด็นมันคือเรื่องการออกแบบตัวระบบ — ทั้งระดับโครงสร้างพื้นฐานและระดับส่วนติดต่อผู้ใช้ — ไม่ว่าจะเป็น database schema ช่องหรือปุ่มที่มีให้กดในหน้าจอ UI หรือวิธีการทำ data validation ที่ทำให้ข้อมูลที่อยู่นอกเหนือไปจากที่ผู้ออกแบบระบบอนุญาต มันกรอกไม่ได้ รวมไปถึงคู่มือใช้งาน/การอบรมการใช้งานที่ทำให้เจ้าหน้าที่ที่เป็นผู้กรอกยึดอยู่กับคุณค่าบางอย่าง แม้ตัวระบบจะไม่ได้บังคับ (ในระบบที่ตัวเจ้าของข้อมูลไม่ได้เป็นผู้กรอกเอง)

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

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

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

ซอฟต์แวร์เป็นสถาปัตยกรรมที่กำหนด (อนุญาต/ไม่อนุญาต) ทางที่เราจะใช้ชีวิต{ใน/กับ/ด้วย}สภาพแวดล้อมนี้ได้ ไอเดียเดียวกับที่เลซสิกเสนอว่า code is law น่ะแหละ

เผยแพร่ครั้งแรก 31 มีนาคม 2564 บนเฟซบุ๊ก

Web Character Simplification Chart 0.1 #opendream

ก่อนจะประมวลผลข้อความ เราจำเป็นต้องทำความสะอาดข้อความเสียหน่อย ทั่ว ๆ ไปที่จำเป็นต้องทำ ก็เช่น แปลง new line (\r\n หรือ \n), หรือแปลงให้อยู่ในชุดอักขระ (character set) ที่โปรแกรมใน processing pipeline จะทำงานได้ เช่นแปลง ä เป็น ae หรือแปลง “ ” เป็น ” “, หรือการ normalize ลำดับอักขระ เช่น น.หนู+สระอำ+ไม้โท → น.หนู+ไม้โท+สระอำ, หรือไปถึงขั้นซับซ้อน อย่างแก้ตัวสะกด

(กรณีเป็นงานลักษณะจดหมายเหตุ หรือ archival ก็อาจจำเป็นต้องเก็บตัว raw text ก่อนแปลงเอาไว้ด้วย เพราะการแปลงอาจจะ(และมักจะ)เป็น lossy คือแปลงไปแล้วแปลงกลับมาได้ไม่เหมือนเดิม เช่นตัวอย่างข้างบน ที่แปลง “ ” เป็น ” “)

การทำความสะอาดข้อความ หรือ text cleansing นี้ มีจุดประสงค์หลายอย่าง อย่างหนึ่งก็เพื่อเพิ่มความต้องตรงกัน (integrity) ภายในเนื้อข้อความ ซึ่งกรณีถ้าจะเอาข้อความนี้ไปประมวลผลทางสถิติ เช่นเอาไปฝึกเครื่อง (machine learning) ความต้องตรงกันภายในข้อความนี้ ก็มีผลต่อความแม่นยำของตัวแบบที่จะฝึกได้

จุดประสงค์อีกอย่างของการทำความสะอาดข้อความ ก็เพื่อลดความซับซ้อนของการประมวลผลด้วย ไม่ว่าจะเป็นการลดความซับซ้อนของตัวแบบ หรือการลดความซับซ้อนของเงื่อนไขในโปรแกรม เช่น ทำให้เขียน regular expression ได้สะดวกขึ้น

สำหรับแอปพลิเคชั่นการค้นหาและการทำดัชนี การทำความสะอาดข้อความ รวมไปถึงการทำให้ข้อความมันซับซ้อนน้อยลง (ไม่ว่าจะในทางลำดับอักษร ซึ่งจะมีผลต่อขนาดของ word set หรือการลดขนาดของ character set ด้วยการยุบตัวอักษรบางตัวเข้าด้วยกัน) จะช่วยให้ดัชนีมีขนาดเล็กลงด้วย และถ้าใช้ประกอบกับตารางการแทนอักษร/คำ (replacement table) ก็จะช่วยให้โอกาสการเจอคำที่ค้นหา มีมากขึ้น เนื่องจากลดผลกระทบจากการสะกดไม่ตรงกัน (spelling variations) (จริง ๆ จะใช้ replacement table อย่างเดียวก็ได้ แต่กรณีนั้น search space ก็จะใหญ่ขึ้น มีผลต่อประสิทธิภาพ)

ในตอนที่เขียน JavaScript สำหรับใช้กับ Roti ก็คิดไว้าว่าจะเจอปัญหาลักษณะนี้ ซึ่งจะมีผลต่อการคำนวณหาบล็อกโพสต์ที่ใกล้เคียง (ดูตัวอย่างได้ที่ท้ายโพสต์นี้ ตรงที่เขียนว่า ‘roti thinks you may like these posts…’) เลยให้จาวาสคริปต์ทำความสะอาดข้อความนิดหน่อย ก่อนจะส่งไปเซิร์ฟเวอร์

เนื่องจาก Roti ทำงานกับเอกสารเว็บ ซึ่งมี ‘ปัญหา’ อีกอย่าง คือการใช้ HTML/XML entities แทนตัวอักษร เช่นใช้ &amp; เพื่อแทนอักษร & ดังนั้นก่อนจะทำอะไรกับข้อความ จึงควร decode entities พวกนี้ออกมาก่อน

กรณีของ HTML entities ถ้าใช้ PHP สามารถใช้ฟังก์ชั่น html_entity_decode($text) ได้เลย แต่ในจาวาสคริปต์มันไม่มี (หรือผมไม่รู้ว่ามันมี) ก็เลยใช้แทนที่สตริงแบบบ้าน ๆ ไป

ตารางข้างล่างปรับแก้มาจากตัวจาวาสคริปต์ roticlient.js และใส่รายละเอียดเพิ่มเติมนิดหน่อย ยินดีรับคำแนะนำครับ

possible replacements ในตารางนั้น เป็นเพียงคำแนะนำตั้งต้น การจะเลือกใช้อะไร ขึ้นอยู่กับแอปพลิเคชั่นด้วย เช่น ตัวเลือกที่เหมาะกับการเอาไปทำดัชนี ก็อาจจะไม่เหมือนกับตัวเลือกที่เหมาะกับการเอาไปแสดงผล เช่น zero-width space ถ้าทำดัชนี การแทนด้วย space น่าจะเหมาะ แต่ถ้าจะเอาไปแสดงผล การลบมันทิ้งไปเลย น่าจะเหมาะกว่า

Web Character Simplification Chart 0.1

Throw away extra semantics for a simpler text processing. This is only a suggestion. Apply to your needs accordingly.

Character Name Character Unicode ASCII range? HTML Entities Possible Replacements
Space     yes    
Non-breaking space   U+00A0 yes &nbsp; (space)
Zerowidth space   U+200B     (space), <delete>
 
Soft hyphen   U+00AD yes &shy; <delete>
 
Hyphen-Minus U+002D yes    
Hyphen U+2010     – (hyphen-minus)
Minus sign U+2212   &minus;
Figure dash U+2012    
En dash U+2013   &ndash; -, —
Em dash U+2014   &mdash; -, —
Horizontal bar U+2015    
Armenian hyphen ֊ U+058A    
Hebrew magaf ־ U+05BE    
Mongolian todo hyphen U+1806    
Japanese chōonpu U+30FC    
 
Hyphen bullet U+2043     * (star), -, <delete>
Small bullet U+2022     *, -, <delete>
 
Tilde ~ U+007E yes &tilde;  
Swung dash ˜ U+2053     ~ (tilde)
Wave dash U+301C     ~
Wavy dash U+3030     ~

ด้านล่างนี้ เป็นตัวอย่างโค้ดที่แทนที่ตัวอักษรต่าง ๆ จาก roticlient.js


return str.replace(/(&nbsp;|&#8208;|&#8210;|&ndash;|&#8211;|&mdash;|&#8212;|&#8213;|&#8275)/g, ' ')
.replace(/(&shy;|&#xAD;|&#173;|&#x200B;|&#8203)/g,'')
.replace(/[\u200b\u200d\u00ad]/g, '')
.replace(/[!\?;:"'`“”^\*\+\-_\(\)\[\]\{\}#@&~\.,\\\/\|]/g, ' ')
.replace(/\s+/g, ' ');

ติดตามการพัฒนา Roti ได้จาก Opendream’s blog

(โพสต์นี้ให้ @pittaya เนื่องจากเคยถามเอาไว้เมื่อนานเมือกแล้ว)

technorati tags:
,
,

encode("UTF-8", "ignore") ข้าม ๆ เรื่องที่ทำไม่ได้ใน Python

หลังจากเอา python-libthai ของวีร์มาใช้กับข้อมูลที่ได้มาจากเว็บ ก็พบปัญหาเรื่อง character encoding นิดหน่อย

libthai นั้นปัจจุบันทำงานกับข้อมูลที่เป็นภาษาไทย 8 บิตอยู่ (น่าจะเป็น TIS-620) ตัว python-libthai เลยมีขั้นตอนการแปลงจากยูนิโค้ดไปเป็น 8 บิตก่อน
ทีนี้ ปรากฏว่า encoder “CP874”, “TIS_620” และ “ISO8859_11” ของ Python มันดันแปลงตัวอักษรบางตัวไม่ได้ (เนื่องจากใน charset พวกนั้น มันไม่มีตัวอักษรดังกล่าว) โปรแกรมก็เลยจะตาย ถ้าไปเจออักษรพวกนั้น

ก่อนตายมันจะโวยทำนองว่า :

UnicodeEncodeError: 'charmap' codec can't encode character
u'\u200b' in position 3560: character maps to <undefined>

วิธีแก้แบบถึก ๆ คือ เอาหูไปนาเอาตาไปไร่ซะ ignore มัน ด้วยการไปแก้ แฟ้มชื่อ libthai.c ของ python-libthai (แฟ้มนี้เป็น wrapper ที่ไปเรียก libthai ให้)

หาบรรทัดที่เรียกฟังก์ชั่น PyUnicode_Encode/Decode แล้วแก้พารามิเตอร์ตัวที่สี่เป็น “ignore” ซะ

เช่น จาก


PyObject *txt_cp874 =
    PyUnicode_Encode(s1, s1_len, "CP874", NULL);
tok =
    PyUnicode_Decode(buffer, tok_len, "CP874", NULL);

เป็น


PyObject *txt_cp874 =
    PyUnicode_Encode(s1, s1_len, "CP874", "ignore");
tok =
    PyUnicode_Decode(buffer, tok_len, "CP874", "ignore");

แล้ว sudo python setup.py install ใหม่อีกรอบ (อย่าลืมล้าง build เก่าทิ้งก่อน) ก็น่าจะใช้ได้แล้วครับ

ลิงก์ : Python Unicode How-to

technorati tags: 

Time for Unicode ?

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

จะ Windows-874, TIS-620 หรือ ISO-8859-11 ก็คงไม่เพียงพอแล้ว สำหรับโลกยุคอินเทอร์เน็ตและสังคมพหุภาษา แม้แต่เอกสาร “ภาษาไทย” ในปัจจุบันก็ยังมีตัวอักษรละตินหรือสัญลักษณ์พิเศษต่าง ๆ แทรกอยู่มากมาย ซึ่งบางตัวก็ไม่ได้มีอยู่ทั้งใน Windows-874, TIS-620 และ ISO-8850-11

ได้เวลาเปลี่ยนมาใช้ Unicode ให้หมดรึยังนะ ?
(สำหรับงานส่วนใหญ่ ที่ขนาดพื้นที่จัดเก็บข้อมูล/แบนด์วิธ ไม่ได้เป็นข้อจำกัดสำคัญอีกต่อไปแล้ว)

ทั้งหน้าเว็บ ไฟล์เอกสาร metadata โค้ดโปรแกรมต่าง ๆ

แต่จะใช้อะไรดี UTF-8 หรือ UTF-16 ?

Windows NT ขึ้นไป, Windows CE, Java, .NET, Mac OS X และ Qt แพลตฟอร์มเหล่านี้ ใช้ UTF-16 เป็น native character set
แต่ถ้าเป็นโลก Unix และอินเทอร์เน็ต UTF-8 ก็แพร่หลายกว่า

ถ้าพูดถึงเฉพาะที่เกี่ยวข้องกับอินเทอร์เน็ต ไปใช้ UTF-8 กันให้หมดเลยดีมั๊ย ? สำหรับข้อมูลภาษาไทย ทั้งหน้าเว็บ ฐานข้อมูล metadata ฯลฯ

ข้อดี-ข้อเสีย ? อะไรคืออุปสรรค ?

technorati tags:
,
,

Encodings/Charsets in Java

Encoding, Canadian Mind Products’s Java Glossary
a very detailed resources on encoding/charset-related stuffs in Java ละเอียดมาก

List of supported encodings, how to convert them, guide to Readers, other classes/methods, etc.

Plus, Unicode in Java by Jason Orendorff

(เมื่อคืนทดลองใช้ iBATIS (ORM ตัวนึง) กับภาษาไทยใน MySQL ไม่เวิร์กแฮะ ฟิลด์ไหนที่เป็นภาษาไทย get ออกมาแล้วกลายเป็น null หมดเลย)

technorati tags:
,
,

Unicode, XML, TEI, Ω and Scholarly Documents

โดย Yannis HARALAMBOUS เสนอที่ 16th International Unicode Conference, Amsterdam, 2000

สองตัวแรกส่วนใหญ่คงเคยได้ยินกันมาบ้างแล้ว อยากรู้รายละเอียด ลองอ่าน Unicode, XML

TEI คือ Text Encoding Initiative เป็นคล้ายๆ “ข้อแนะนำ” สำหรับการจัดเก็บข้อมูลในคอมพิวเตอร์ ก่อนหน้านี้ใช้ SGML ตอนนี้เริ่มค่อยๆ ปรับเปลี่ยนมาใช้ XML ละ

หมายเหตุ: SGML, XML เป็นเพียงแค่ markup language หรือพูดอีกอย่างคือ เป็นเพียงแค่เครื่องมือในการเข้ารหัสเท่านั้น แต่ไม่ได้บอกว่า จะเข้ารหัสยังไง ตัวอย่างเช่น สมมติมี โคลงสี่สุภาพอยู่บทนึง จะเก็บยังไง เก็บทั้งบทรวมกันเป็นก้อนเดียวโดยใส่เครื่องหมายแบ่งบรรทัดลงไปด้วย หรือว่าแยกเป็นสี่ส่วน แต่ละส่วนมีโครงสร้างเหมือนกัน แล้วให้แต่ละส่วนเก็บแต่ละบาท (โคลงสี่สุภาพ 1 บท มี 4 บาท) แล้วจากนั้นค่อยใส่สี่บาทนี้เข้าไปในตัวบทอีกที แล้วเอาตัวบทไปใส่ในตัวโคลงอีกที ฯลฯ อะไรพวกนี้ นี่คือสิ่งที่ TEI ทำ
แล้วเอาไปใช้ทำอะไรอ่ะ? – ดู The Oxford Text Archive ได้ เค้าเก็บเอกสารต่างๆ หลายประเภท เอาไว้ในรูปแบบอิเล็กทรอนิกส์

ส่วน Ω (เพิ่งเคยเห็นวันนี้) คือส่วนขยายของ TeX เพื่อรองรับ Unicode (ไม่ใช่ จมูกหมีอันใหญ่ แต่อย่างใด)

ได้ลิงก์ของบทความนี้มาจากบล็อกพี่พูลลาภ ขอบคุณมากครับ 🙂
พอดีกำลังดูเรื่อง TEI กะ Unicode อยู่ อันนี้ใช้ได้เลย มีพูดถึงประเด็นที่น่าสนใจและน่าจะเอามาใช้ได้ด้วย thanx thanx 😀

Character encoding issues

A tutorial on character code issues – covers many issues in character encoding

Germanic Lexicon Project:

Multiple Representations – normalization, canonical decompositions, compatibility decompositions, etc.

Linguistic Sorting – how characters are sorted in an Oracle environment

Unicode in MySQL – with PHP examples

Character Encoding and the Web – with Thai example: “เอกชัย ศรีวิชัย”สุดทน เจอเทปผี ซี.ดี.เถื่อนแย่งตลาด สั่งลูกน้องไล่กระทืบพ่อค้าขายซี.ดี.เถื่อน พร้อมประกาศลั่น ฝากบอกเอเย่นต์ใหญ่ว่า “เอกชัย สั่งให้ทำ” !

Common Locale Data Repository

Common Locale Data Repository (CLDR) จัดทำโดยองค์กร Unicode เป็นฐานข้อมูล locale data กลาง ให้โปรแกรมอื่นๆ นำไปใช้ต่อ เพื่อให้แต่ละโปรแกรม มี locale data ที่ถูกต้องตรงกัน ใช้งานร่วมกันได้ และไม่สับสน

อ้างอิง L10n.opentle.org

เพิ่มเติม: พี่เทพ ตอบคำถาม เรื่องข้อมูลที่ OOo กับ CLDR ไม่ตรงกัน และบางแห่งน่าจะผิด

เพิ่มเติม 2: พี่สัมพันธ์ ให้ความเห็น และ อธิบายลักษณะข้อมูล ว่าจะเข้าไปดูได้ยังไง และให้ช่วยกันดู+แก้ไขหน่อย 🙂

Thai locale data in CLDR
มีข้อมูลจากหลายแหล่ง ทั้งข้อมูลกลาง (Common), Windows, Sun JDK, IBM JDK, OpenOffice.org, AIX, และ Linux (ไม่มี Solaris? .. เอ แปลก)
ถ้าเกิดว่า ทุกๆ อันถูกต้อง และตรงกันหมด อันนั้นคือ เยี่ยม