ทำไมการเพิ่ม Furigana ในไฟล์ Word ถึงเป็นฝันร้ายของโปรแกรมเมอร์
หลายคนคงเคยเจอปัญหาเวลาอ่านภาษาญี่ปุ่นแล้วเจอตัวคันจิ (ตัวอักษรจีนที่ใช้ในภาษาญี่ปุ่น) ที่อ่านไม่ออกใช่ไหมครับ วิธีแก้ที่นิยมที่สุดคือการเติม Furigana (คำอ่านตัวเล็กๆ ที่อยู่เหนือตัวคันจิ) เพื่อช่วยให้อ่านง่ายขึ้น แต่งานนี้ถ้าทำด้วยมือใน Microsoft Word จะเหนื่อยมากถ้าต้องทำกับเอกสารยาวๆ
ผมเลยคิดจะเขียนโปรแกรมชื่อ EZFurigana เพื่อช่วยเติมคำอ่านให้โดยอัตโนมัติ ผมมองว่ามันน่าจะเป็นแค่ส่วนเสริมเล็กๆ ที่ไม่น่ามีปัญหาอะไร ผมกะว่าจะแค่เปิดไฟล์เอกสาร ค้นหาข้อความภาษาญี่ปุ่น ใส่คำอ่านเข้าไป แล้วบันทึกไฟล์กลับมาเหมือนเดิม ฟังดูเหมือนจะง่ายแต่จริงๆ แล้วมันคือฝันร้ายครับ
การเขียนโปรแกรมจัดการไฟล์ DOCX (นามสกุลไฟล์เอกสารของ Word) ไม่ได้ง่ายเหมือนการเปิดไฟล์ข้อความทั่วไป เพราะโครงสร้างของมันซับซ้อนกว่าที่ตาเห็นมาก ถ้าเราไม่เข้าใจว่ามันเก็บข้อมูลอย่างไร เราอาจจะทำไฟล์พังจนเปิดไม่ได้เลยครับ
ความจริงเบื้องหลังไฟล์ DOCX ที่คุณไม่เคยรู้
ถ้าคุณคิดว่าไฟล์ .docx เป็นแค่กระดาษเปล่าที่มีตัวอักษรเรียงกัน คุณคิดผิดถนัดครับ จริงๆ แล้วมันคือ ZIP package (ไฟล์ที่ถูกบีบอัดรวมหลายๆ ไฟล์เข้าด้วยกัน) ที่ข้างในมีทั้งไฟล์ XML (ภาษาที่ใช้จัดโครงสร้างข้อมูล), รูปภาพ, แบบอักษร และสไตล์การจัดหน้ากระดาษ
ข้อมูลเนื้อหาหลักของเอกสารส่วนใหญ่จะถูกเก็บไว้ในไฟล์ที่ชื่อว่า document.xml ครับ การแก้ไขไฟล์นี้โดยตรงดูเหมือนจะเป็นวิธีที่ง่ายที่สุด แต่ปัญหาคือถ้าเราเผลอลบแท็ก (เครื่องหมายกำกับข้อมูล) บางอย่างไปแค่ตัวเดียว ไฟล์เอกสารทั้งไฟล์จะพังทันทีและ Word จะเปิดไม่ได้อีกเลย
มือใหม่หลายคนมักพลาดตรงที่พยายามเขียนโปรแกรมไป "เขียนทับ" ทั้งไฟล์ ซึ่งเสี่ยงเกินไปครับ วิธีที่ปลอดภัยกว่าคือการเจาะจงแก้ไขแค่ส่วนของ document.xml โดยพยายามรักษาส่วนประกอบอื่นของไฟล์ไว้ให้ครบถ้วนที่สุดครับ
เมื่อประโยคไม่ได้ถูกเก็บเป็นประโยค
ปัญหาถัดมาคือ Word ไม่ได้เก็บข้อความเป็นประโยคยาวๆ อย่างที่เราเห็นครับ แต่มันจะหั่นข้อความเป็นชิ้นเล็กๆ ที่เรียกว่า Run (ส่วนของข้อความที่มีการจัดรูปแบบเดียวกัน) ยิ่งถ้าคุณเปลี่ยนตัวหนา เปลี่ยนสี หรือใส่ลิงก์ Word ก็จะยิ่งซอยข้อความออกเป็นชิ้นเล็กชิ้นน้อยมากขึ้นไปอีก
สมมติคุณมีประโยคว่า "東京駅" (สถานีโตเกียว) โปรแกรมของคุณอาจจะมองไม่เห็นคำนี้เป็นก้อนเดียวกัน เพราะมันอาจจะถูกหั่นกลางประโยคเพราะการจัดรูปแบบที่ต่างกัน ถ้าคุณสั่ง Find and Replace (คำสั่งค้นหาและแทนที่) แบบดื้อๆ โปรแกรมจะหาคำไม่เจอเพราะมันถูกตัดขาดออกจากกันครับ
ดังนั้นเวลาเขียนโปรแกรมจัดการเอกสาร คุณต้องมีระบบที่คอยติดตาม (Track) ตำแหน่งของข้อความให้แม่นยำครับ ถ้าส่วนไหนของเอกสารมีความซับซ้อนเกินไปจนเสี่ยงจะพัง ผมแนะนำว่าให้ข้ามส่วนนั้นไปเลยดีกว่าพยายามฝืนแก้ไขครับ
// ตัวอย่างการจำลองโครงสร้างข้อความที่ถูกหั่น
let runs = [
{ text: "โตเกียว" }, // ส่วนที่ 1
{ text: "สถานี" } // ส่วนที่ 2
];
// ถ้าเราจะหาคำว่า "โตเกียวสถานี" เราต้องรวมร่างก่อน
let fullText = runs.map(r => r.text).join("");
console.log(fullText); // ผลลัพธ์: "โตเกียวสถานี"
โค้ดด้านบนแสดงการรวม runs (ชิ้นส่วนข้อความ) เข้าด้วยกันครับ เราใช้ฟังก์ชัน map เพื่อดึงข้อความออกมา แล้วใช้ join เชื่อมเข้าด้วยกันเพื่อให้เราค้นหาคำได้ง่ายขึ้นครับ
การใส่ Furigana ด้วยภาษา Markup ของ Word
Word มีระบบรองรับการใส่คำอ่านที่เรียกว่า Ruby (ตัวอักษรช่วยอ่าน) ครับ โครงสร้างในไฟล์ XML จะประกอบด้วย w:ruby (ตัวเปิดคำอ่าน), w:rubyBase (คำคันจิหลัก) และ w:rt (คำอ่านที่แสดงด้านบน) ซึ่งต้องวางให้ถูกตำแหน่งเป๊ะๆ
ความยากคือเราต้องแยกก้อน Run เดิมออกเป็นสามส่วน คือ ส่วนหน้าคำคันจิ ส่วนที่เป็นคันจิพร้อมคำอ่าน และส่วนหลังคันจิ โดยที่ต้องรักษาสไตล์เดิมของเอกสารไว้ให้ครบครับ ถ้าพลาดไปนิดเดียว ระยะบรรทัดหรือตัวหนาตัวเอียงจะเพี้ยนทันที
กฎเหล็กคืออย่าใส่คำอ่านซ้ำซ้อนครับ ก่อนจะเติม w:ruby เข้าไป คุณต้องเขียนโปรแกรมเช็คก่อนว่าตรงนั้นมีคำอ่านอยู่แล้วหรือยัง เพื่อไม่ให้เอกสารดูรกจนอ่านไม่รู้เรื่องครับ
ปัญหาเรื่องการแสดงผลและการพรีวิว
พอเราเขียนโค้ดแก้ไขไฟล์ .docx สำเร็จแล้ว ปัญหาถัดมาคือการพรีวิว (ดูตัวอย่างก่อนดาวน์โหลด) บนเว็บครับ เบราว์เซอร์ไม่ได้ถูกออกแบบมาให้อ่านไฟล์ Word ได้โดยตรง ทำให้เราต้องหาทางแปลงไฟล์ให้แสดงผลได้เหมือนที่ Word ทำจริงๆ
ผมเลือกใช้ LibreOffice (ชุดโปรแกรมสำนักงานฟรี) มาช่วยแปลงไฟล์ให้เป็นรูปแบบที่เว็บแสดงผลได้ครับ แต่มันก็เจอปัญหาเรื่องการจัดวางตัวอักษรแบบเอเชีย โดยเฉพาะตัว Ruby ที่มักจะมีระยะห่างไม่เท่ากับที่ Word แสดงผลจริงๆ ทำให้บางจุดดูแปลกตาไปบ้าง
สำหรับมือใหม่ที่กำลังทำโปรเจกต์แนวนี้ อย่าคาดหวังความสมบูรณ์แบบ 100% ครับ การยอมรับว่าโปรแกรมของเราอาจจะแสดงผลต่างจาก Word เล็กน้อย เป็นการแลกเปลี่ยนที่คุ้มค่ากว่าการพยายามแก้ไขจนระบบพังครับ
สรุป: บทเรียนจากการทำโปรเจกต์จริง
สุดท้ายแล้ว EZFurigana ก็สำเร็จออกมาได้โดยการผสมผสานหลายขั้นตอนครับ เริ่มจากการอัปโหลดไฟล์ แยกโครงสร้าง XML ออกมาจัดการ ใส่คำอ่านตามกฎของ Ruby แล้วนำกลับไปประกอบร่างใหม่ ก่อนจะใช้ LibreOffice ช่วยเรนเดอร์ภาพพรีวิวให้ผู้ใช้เห็นก่อนโหลดจริง
การทำโปรเจกต์นี้สอนผมว่า งานที่ดูเหมือน "เล็กน้อย" ในสายตาเรา อาจซ่อนความซับซ้อนมหาศาลไว้ข้างใต้ครับ หัวใจสำคัญคือการค่อยๆ แกะปัญหาทีละส่วน อย่ามองข้ามรายละเอียดเล็กๆ น้อยๆ และที่สำคัญที่สุดคือต้องเน้นที่ความปลอดภัยของไฟล์ผู้ใช้เป็นอันดับหนึ่งเสมอ
ถ้าคุณกำลังฝึกเขียนโค้ดและอยากทำเครื่องมืออะไรสักอย่าง ผมแนะนำให้เริ่มจากไฟล์เล็กๆ ก่อนครับ ลองดูโครงสร้างของไฟล์ที่คุณจะจัดการให้ดี แล้วค่อยๆ เขียนโปรแกรมเข้าไปแก้ทีละนิด ดีกว่าการพยายามทำทุกอย่างให้เสร็จในรวดเดียวครับ
ที่มา: Adding Furigana to Word Documents is a Nightmare — DEV Community