Blog
Shipping one Android app in English, Myanmar and Thai
Practical notes on strings, plurals, per-app language switching, fonts and testing when one app has to speak three languages.
ทำแอป Android ตัวเดียวให้พูดได้ทั้งอังกฤษ พม่า และไทย
การแปลแอปฟังดูเหมือนงานแค่เรื่อง string: ก๊อป strings.xml ส่งให้คนที่
พูดภาษานั้น จบ แต่พอเปิด build ภาษาพม่า ปุ่มครึ่งหนึ่งตัวอักษรโดนตัด build
ภาษาไทยตัดบรรทัดกลางพยางค์ ส่วนภาษาอังกฤษก็โผล่ "1 items" ออกมา นี่คือ
สิ่งที่ผมเช็กทุกครั้งเมื่อแอปต้องรองรับภาษาอังกฤษ พม่า และไทย
String: หนึ่งภาษาหนึ่งโฟลเดอร์ และห้ามต่อประโยค
values/เก็บภาษาอังกฤษ ซึ่งเป็น fallback ของ string ที่ยังไม่ได้แปลด้วยvalues-my/คือภาษาพม่า และvalues-th/คือภาษาไทย- อย่าประกอบประโยคจากชิ้นส่วน "Paid " + name + " today" ใช้ได้แค่ใน
ภาษาอังกฤษ ภาษาพม่าและไทยเรียงกริยากับชื่อต่างกัน ให้ใช้ string เดียว
ที่มี placeholder:
<string name="paid_today">จ่ายให้ %1$s แล้ววันนี้</string> - ใส่ comment เหนือแต่ละ string เพื่อให้บริบทกับคนแปล "Back" ที่เป็นปุ่ม กับ "back" ที่แปลว่าหลัง เป็นคนละคำกันในภาษาไทย
Plural ไม่เหมือนกันทุกภาษา
ภาษาอังกฤษต้องมี one และ other ส่วนภาษาพม่าและไทยไม่เปลี่ยนรูปคำนาม
ตามจำนวน จึงใช้แค่ other แต่ก็ควรประกาศ plural ให้ถูกต้องอยู่ดี เพื่อให้
แต่ละภาษาได้กฎของตัวเอง:
<plurals name="items_count">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
</plurals>
ใน values-my/ และ values-th/ entry เดียวกันจะมีแค่ other ตัวเดียว
พอเรียก pluralStringResource(R.plurals.items_count, n, n) ก็แสดงถูก
ทั้งสามภาษา
ให้ผู้ใช้เลือกภาษาเอง
คนในพม่าและไทยหลายคนตั้งภาษาโทรศัพท์เป็นอังกฤษ แต่อยากอ่านแอปเป็น ภาษาของตัวเอง หรือกลับกัน Android 13 เพิ่มการตั้งค่าภาษารายแอป และ AppCompat ก็ทำให้ API เดียวกันใช้ได้บนเวอร์ชันเก่าด้วย:
AppCompatDelegate.setApplicationLocales(
LocaleListCompat.forLanguageTags("my")
)
เพิ่ม locales_config.xml ที่มี en, my และ th แล้วแอปจะไปโผล่ในหน้า
App languages ของระบบด้วย
ส่วนที่ยากจริงคือตัวอักษร
การแปลทำให้คำถูกต้อง แต่ typography เป็นตัวตัดสินว่าคนจะอ่านออก หรือเปล่า
- ใช้ Unicode ไม่ใช่ Zawgyi เนื้อหาภาษาพม่ารุ่นเก่ามักเป็น Zawgyi ซึ่งเป็น ฟอนต์ที่เอา code point ของ Unicode มาใช้ซ้ำ ให้เก็บและส่งแต่ Unicode และแปลงข้อความที่ import เข้ามาก่อนลงฐานข้อมูล
- ตัวอักษรสูงกว่า ภาษาพม่าและไทยมีเครื่องหมายซ้อนบนและล่าง ความสูง
แบบ fix หรือ
lineHeightที่แน่นเกินไปจะทำให้โดนตัด ปล่อยให้ข้อความวัด ขนาดเอง และทดสอบด้วย string ที่ยาวที่สุด - ไม่มีเว้นวรรคระหว่างคำ ทั้งสองภาษาไม่เว้นวรรคระหว่างคำ การตัดบรรทัด
จึงต้องใช้พจนานุกรม Android จัดการให้ ตราบใดที่ไม่บังคับ
maxLines = 1พร้อม ellipsis กับเนื้อความ - ตัวเลขและวันที่ format ด้วย locale ของผู้ใช้ (
NumberFormat,DateTimeFormatter) แทนการเขียน pattern เอง เครื่องที่ตั้งเป็นไทยอาจใช้ ปีพุทธศักราช
การทดสอบ
เปิด pseudo-locale เพื่อหาข้อความที่ hard-code และ layout ที่ขยายไม่ได้ แคปหน้าจอหลักทุกหน้าในทั้งสามภาษา และก่อนปล่อยให้เจ้าของภาษาอ่านแอป บนโทรศัพท์จริง — ไม่ใช่แค่อ่าน spreadsheet ของ string
ถ้าทำใหม่จะทำอะไรต่างไป
ผมจะเพิ่มโฟลเดอร์ภาษาพม่าและไทยตั้งแต่วันแรก ถึงจะมีแค่ข้อความ placeholder ก็ตาม ทุก layout ที่สร้างโดยมีแค่ภาษาอังกฤษต้องกลับมาแก้ทีหลัง และนั่นช้ากว่าการสร้างให้ยืดได้ตั้งแต่แรกเสมอ