Back to Guides
คู่มือ

10 ข้อผิดพลาด i18n ที่พบบ่อยและวิธีหลีกเลี่ยง

เรียนรู้ข้อผิดพลาดด้าน i18n ที่พบบ่อยที่สุดที่นักพัฒนาทำ และวิธีแก้ไข ปรับปรุงคุณภาพการโลคาลายส์ของแอปของคุณด้วยแนวทางที่ดีที่สุดเหล่านี้.

5 ระยะเวลาอ่านขั้นต่ำ
โดย shipglobal.dev
#i18n#developer#user experience#best practices#internationalization#common mistakes

i18n ดูเรียบง่าย — จนกว่าคุณจะพบว่าผู้ใช้ภาษาเยอรมันเห็นปุ่มตัดขาด, ผู้ใช้ภาษาญี่ปุ่นได้ส่วนประโยคที่ถูกตัด, และผู้ใช้อาราบิกเห็นเลย์เอาต์ที่เสียหาย นี่ไม่ใช่กรณีขอบเขต แต่เป็นผลลัพธ์ที่คาดการณ์ได้ของข้อผิดพลาดทั่วไปที่ทีมพัฒนาส่วนใหญ่ทำเมื่อเริ่ม localization ในคู่มือฉบับนี้เราจะผ่าน 10 ข้อผิดพลาด i18n ที่พบบ่อยที่สุด อธิบายว่าทำไมพวกเขาถึงเกิด และจะแสดงให้คุณเห็นทีละขั้นตอนว่าจะลบข้อผิดพลาดแต่ละข้ออย่างไร ไม่ว่าคุณจะสร้างแอปใหม่หรือปรับปรุงโปรเจ็กต์เดิม — หลีกเลี่ยงกับดักเหล่านี้จะช่วยคุณประหยัดสัปดาห์ของ debugging

ข้อผิดพลาด #1: สตริงที่ฮาร์ดโค้ด

ข้อผิดพลาด i18n พื้นฐานคือการใส่ strings ด้วยมือ (hardcoding) เกิดขึ้นเพราะนักพัฒนามุ่งเน้นที่ทำให้ฟีเจอร์ใช้งานได้ก่อน แล้ววางแผนว่าเดี๋ยวค่อยทำความสะอาด แต่แล้วความสะอาดก็ติดขัดมักจะไม่เกิดขึ้นและมี strings หลายพันอยู่ในหลายไฟล์

['ติดตั้ง i18n framework ของคุณก่อนเขียน UI สายแรก', 'ใช้ปลั๊กอิน Linter เพื่อค้นหาข้อความ hardcoded ใน templates และ components', 'ทำให้ keys za tafsiri ziwe descriptive na zishikiane na feature au page']

ตั้งค่าเฟรมเวิร์ก i18n ของคุณก่อนเขียนบรรทัด UI แรก

ใช้ปลั๊กอินลินต์เพื่อตรวจหาสตริงที่ฝังในเทมเพลตและคอมโพเนนต์

ให้กุญแจการแปลมีคำอธิบายชัดเจนและจัดเรียงตามฟีเจอร์หรือหน้า

สถานการณ์ทั่วไป

1

นักพัฒนาซอฟต์แวร์เขียนป้ายปุ่มไว้ภายใน JSX โดยตรง: <button>Submit Order</button>.

2

แอปถูกปล่อยเป็นภาษาอังกฤษและทำงานได้อย่างถูกต้อง หกเดือนต่อมา บริษัทขยายไปยังเยอรมนี

3

ทีมทดสอบ localization พบมากกว่า 2,000 strings ที่ hardcoded การปรับปรุงจะใช้เวลา 3 สัปดาห์และทำให้เกิดบั๊ก 47

ทำไมถึงเป็นปัญหา

ในฐานข้อมูลโค้ดที่พัฒนาแล้วStrings ที่ hardcode อาจมีเป็นพันๆ ไฟล์ การแยกออกภายหลังจะต้องแก้ไขทุกไฟล์ ทุกส่วน และเสี่ยงต่อการเกิด regressions ทุกที่

Strings ที่ถูก hardcode อยู่ในโค้ดต้นฉบับ, เทมเพลต หรือส่วนประกอบใดๆ และไม่สามารถดึงออก, แปล หรือเปลี่ยนแปลงขณะรันไทม์ได้โดยไม่แก้โค้ด

ผู้ใช้งานใน locale ที่ไม่ใช่ภาษาอังกฤษจะเห็นองค์ประกอบ UI ที่ไม่ได้รับการแปลผสมกับข้อมูลที่แปลแล้ว ซึ่งทำให้ภาพรวมดูสับสนและไม่เป็นมืออาชีพ

วิธีแก้ไข

ย้ายข้อความที่มองเห็นโดยผู้ใช้ทั้งหมดไปยังไฟล์ทรัพยากร

1

มั่นใจว่าเริ่มต้นกรอบงานแปล (เช่น next-intl, react-i18next, vue-i18n) ก่อนเขียนคอมโพเนนต์แรกของคุณ.

2

สร้างโครงสร้างไฟล์ทรัพยากร (เช่น messages/de.json) และอ้างอิง strings ทั้งหมดด้วยคีย์การแปลอย่าง t('checkout.submitButton').

3

เพิ่มกฎ Linting หรือ Pre-Commit Hook ที่ระบุ literal ของสตริงอย่างไม่ถูกต้องในส่วน UI

ข้อผิดพลาด #10: แปลทุกอย่างตามตัวอักษร

ไม่เนื้อหาทั้งหมดควรถูกแปล ชื่อแบรนด์ ชื่อบริษัททางกฎหมาย คำศัพท์ทางเทคนิค และชื่อผลิตภัณฑ์บางชนิดควรคงในภาษาเดิม การแปลมากเกินไปอาจก่อให้เกิดปัญหาทางกฎหมาย ความสอดคล้องของตรา และความสับสนของผู้ใช้งาน

["ดูแลพจนานุกรม 'ไม่แปล' และแบ่งปันกับนักแปลทุกราย", 'ใช้ส่วนที่ถูกล็อคหรื namespaces แยกสำหรับชื่อแบรนด์และศัพท์ทางกฎหมาย', 'จัดทำบันทึกบริบทเสมอสำหรับสตริงที่มีความหมายหลายทาง เพื่อป้องกันการแปลที่ผิด']

รักษาพจนานุกรม 'ไม่แปล' และแบ่งปันให้กับนักแปลทุกคน

ใช้ส่วนที่ถูกล็อกหรือ namespaces แยกสำหรับคำที่เกี่ยวกับแบรนด์และข้อกำหนดทางกฎหมาย

โปรดระบุคำอธิบายบริบทเสมอสำหรับสตริงที่มีหลายความหมาย เพื่อป้องกันการแปลผิด

สถานการณ์ทั่วไป

1

ไฟล์การแปลประกอบด้วยชื่อบริษัท 'CloudForge Inc.' และคำศัพท์ทางเทคนิค 'OAuth 2.0 Token' ในรูปแบบสตริงที่สามารถแปลได้ทั่วไป

2

ผู้แปลภาษาสเปนแปล 'CloudForge' เป็น 'ForjaNube' และ 'OAuth 2.0 Token' เป็น 'ficha OAuth 2.0'.

3

ผลลัพธ์: ผู้ใช้จะไม่ค้นหาบริษัทนี้ด้วยชื่อจริงของมัน และนักพัฒนาที่อ่านเอกสารภาษาสเปนจะสับสนกับศัพท์เทคนิคที่แปลออกมาไม่รู้จัก

ทำไมถึงเป็นปัญหา

ชื่อแบรนด์ที่แปลผิดหนึ่งชื่อในเอกสารทางกฎหมายอาจทำให้สัญญาเป็นโมฆะ การแก้ไขการแปลมากเกินไปจำเป็นต้องตรวจสอบคำทุกคำในทุกภาษา — เป็นงานที่ต้องใช้หลายสัปดาห์

หากข้อความทั้งหมดถูกส่งไปแปลโดยไม่มีบริบท นักแปลอาจแปลชื่อแบรนด์ ('Apple' → 'Apfel'), คำศัพท์ทางกฎหมาย ('GmbH' → 'LLC') หรือคำศัพท์ทางเทคนิคที่ควรคงไว้ในภาษาอังกฤษ

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

วิธีแก้ไข

ทำเครื่องหมายเนื้อหาที่ไม่สามารถแปลได้อย่างชัดเจนและจัดทำบันทึกบริบทสำหรับนักแปล

1

สร้างพจนานุกรม 'ไม่แปล' ที่ระบุชื่อแบรนด์ ชื่อผลิตภัณฑ์ บุคคลตามกฎหมาย และศัพท์เฉพาะที่ต้องคงไว้โดยไม่เปลี่ยน

2

Tumia namespace tofauti au kunci maalum kwa yaliyomo yasiyotafsiriwa. Zana nyingi za i18n zinaunga mkono vipande vilivyofungwa ambavyo watafsaji hawawezi kuhariri.

3

เพิ่มคอมเมนต์/คำอธิบายสำหรับนักแปลในไฟล์การแปลของคุณ เพื่ออธิบายบริบท: 'นี่คือชื่อแบรนด์ — ไม่แปล' หรือ 'ศัพท์เฉพาะ — เก็บไว้เป็นภาษาอังกฤษ'

ข้อผิดพลาด #2: การต่อสตริง

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

['อย่าสร้างประโยคโดยการเชื่อมต่อชิ้นส่วนที่แปลแล้ว', 'ใช้ตัวแปรแทนที่ชื่อ ('{name}') แทนตำแหน่ง ({0}) เพื่อความชัดเจน', 'ให้คอมเมนต์บริบทสำหรับนักแปลเพื่ออธิบายว่าตัวแปรแต่ละตัวประกอบด้วยอะไร']

ไม่ควรสร้างประโยคโดยการผูกข้อความที่แปลมา

ใช้ตัวแปรแทนที่ชื่อ ('{name}') แทนตำแหน่ง ({0}) เพื่อความชัดเจน

ให้คำอธิบายบริบทแก่ผู้แปล ซึ่งอธิบายว่าแต่ละ placeholder ประกอบด้วยอะไร

สถานการณ์ทั่วไป

1

นักพัฒนากำลังเขียน: 'You have ' + count + ' items in your ' + cartType + ' cart' — ทำงานได้อย่างสมบูรณ์ในภาษาอังกฤษ

2

ผู้แปลภาษาเยอรมันได้รับสามชิ้นส่วนแยกจากกันและไม่สามารถสร้างประโยคที่ถูกต้องทางไวยากรณ์ได้ เพราะลำดับคำต้องเปลี่ยนแปลง

3

ผลลัพธ์: ผู้ใช้งานชาวเยอรมันเห็น 'Sie haben 5 Artikel in Ihrem Warenkorb Standard' — ราบรื่นน้อยและไม่เป็นมืออาชีพ

ทำไมถึงเป็นปัญหา

แต่ละสตริงที่เชื่อมต่อกันเป็นระเบิดเวลาในตัวเอง เมื่อมี 20 ภาษาและ 50 สตริงที่เชื่อมกัน จะมีข้อผิดพลาดด้านไวยากรณ์ประมาณ 1,000 จุดที่ต้องแก้ด้วยมือ

การรวมข้อความอย่างเช่น 'ยินดีต้อนรับ ' + ชื่อผู้ใช้ + ', คุณมี ' + จำนวน + ' ข้อความใหม่' ต้องการลำดับคำเฉพาะ นักแปลจะได้รับชิ้นส่วนที่ไม่มีบริบท

ผู้ใช้เห็นประโยคที่ผิดไวยากรณ์ ในภาษาเยอรมัน กริยามักอยู่ท้ายประโยค ในภาษาอาหรับ โครงสร้างทั้งหมดกลับด้าน ผลลัพธ์อ่านเหมือนไร้สาระ

วิธีแก้ไข

ใช้ ICU MessageFormat ซึ่งรองรับกฎ CLDR แบบครบถ้วน

1

แทนที่การเชื่อมต่อด้วยคีย์ข้อความเดียวพร้อมตัวแปรแทนที่: 'cart.summary': 'คุณมี {count} รายการในรถเข็น '{cartType}''

2

ผู้แปลจัดหารูปแบบพหุลที่จำเป็นทั้งหมดสำหรับภาษา เขียน Polish: '{count, plural, one {# plik} few {# pliki} many {# plików} other {# pliku}}'.

3

นักแปลสามารถจัดเรียงใหม่ได้อิสระ: 'ในรถเข็น '{cartType}' ของคุณมี {count} รายการ' — ภาษาเยอรมันที่ถูกต้องตามไวยากรณ์

ข้อผิดพลาด #3: ละเลยการพหูพจน์

ภาษาอังกฤษมีสองรูปพหูพจน์: เอกพจน์และพหูพจน์ นักพัฒนามักคิดว่าทุกภาษาทำงานเหมือนกัน แต่ไม่ใช่ ภาษาโปแลนด์มี 4 รูปแบบ ภาษาอาหรับมี 6 และแม้ภาษาฝรั่งเศสก็มีการจัดการศูนย์แตกต่างจากอังกฤษ

['ใช้ ICU MessageFormat ตลอดเวลา หรือห้องสมุดที่เทียบเท่าสำหรับข้อความที่นับได้', 'อย่าพัฒนาโลจิกพหูพจน์เอง — เชื่อถือกฎ CLDR', 'ทดสอบการผันพหูพจน์ด้วยค่าตัวอย่าง 0, 1, 2, 5, 21 และ 100 เพื่อครอบคลุมทุกประเภท']

ใช้งาน ICU MessageFormat ตลอดเวลา หรือไลบรารีที่เทียบเท่าสำหรับเนื้อหาที่นับได้

อย่าคิดตรรกะรูปพหูพจน์เองเด็ดขาด — เชื่อกฎ CLDR

ทดสอบรูปพหูพจน์ด้วยค่าที่แตกต่างกัน เช่น 0, 1, 2, 5, 21 และ 100 เพื่อครอบคลุมทุกประเภท

สถานการณ์ทั่วไป

1

นักพัฒนากำลังเขียน: count + (count === 1 ? ' Datei' : ' Dateien') — ภาษาเยอรมันถูกต้อง

2

ผู้แปลต้องการ 4 รูปแบบ: 1 plik, 2-4 pliki, 5-21 plików, 22-24 pliki. เฉพาะ ternary ง่ายไม่สามารถถ่ายทอดได้

3

ผลลัพธ์: ผู้ใช้งานภาษาพลินิสท์เห็น '5 pliki' (รูปแบบผิด) แทน '5 plików' (รูปแบบถูกต้อง), และแอปดูเหมือนพัง

ทำไมเรื่องนี้ถึงเป็นปัญหา

ทุกคำนามที่นับได้ในแอปของคุณต้องมีการจัดการพหูพจน์ เมื่อมี 50 สตริงแบบนี้และ 20 ภาษา จะมี 1,000 กฎพหูพจน์ที่จัดการด้วยตนเองยาก

การตรวจสอบ if/else ง่ายๆ (count === 1 ? 'Datei' : 'Dateien') ใช้ได้กับเยอรมันและอังกฤษเท่านั้น CLDR กำหนดหกประเภทการพหุพจน์: zero, one, two, few, many และ other ภาษาแต่ละภาษาจะใช้ subset ต่างกัน

ผู้ใช้เห็นข้อความพหูพจน์ผิดพลาด เช่น '1 ข่าว' หรือรูปแบบพหูพจน์ที่ผิดทั้งหมด ในบริบททางการทำให้ความน่าเชื่อถือเสียหาย

วิธีแก้

ใช้ ICU MessageFormat ซึ่งรองรับกฎการพหุพจน์ของ CLDR ได้ครบถ้วน

1

กำหนดข้อความด้วย ICU ซินทAX: 'fileCount': '{count, plural, one {# Datei} other {# Dateien}}'.

2

ผู้แปลจัดหารูปแบบพหุลทั้งหมดที่จำเป็นสำหรับภาษาของพวกเขา ตัวอย่าง Polish: '{count, plural, one {# plik} few {# pliki} many {# plików} other {# pliku}}'.

3

ไลบรารี i18n ของคุณจะเลือกฟอร์มที่ถูกต้องโดยอัตโนมัติระหว่างรันไทม์ ตามกฎ CLDR ของ Locale ที่ใช้งานอยู่.

ข้อผิดพลาด #4: ความกว้างของส่วน UI ที่คงที่

นักออกแบบสร้างเลย์เอาต์ที่ละเอียดเป็นพิกเซลเป็นภาษาอังกฤษ และนักพัฒนาก็นำไปใช้งานด้วยความกว้างคงที่ แต่ข้อความที่แปลอาจยาวหรืสั้นมาก ภาษาเยอรมันจะยาวกว่าภาษาอังกฤษประมาณ 30% ในขณะที่ภาษาจีนอาจสั้นลงถึง 50%

['ไม่ควรใช้ความกว้างพิกเซลคงที่สำหรับองค์ประกอบที่มีข้อความที่แปลได้', 'วางแผนการขยายข้อความอย่างน้อย 40% เป็นพื้นฐาน — บางภาษาจะขยายมากกว่า', 'ใช้ CSS Flexbox หรือ Grid สำหรับเลย์เอาท์ที่ปรับตามความยาวของเนื้อหา']

ห้ามกำหนดความกว้างพิกเซลคงที่สำหรับองค์ประกอบที่มีข้อความที่แปลได้

ตั้งค่าการขยายข้อความเป็น 40% เป็นค่าพื้นฐาน — บางภาษาอาจขยายมากขึ้น

ใช้ CSS Flexbox หรือ Grid สำหรับเค้าโครงที่ปรับให้เข้ากับความยาวเนื้อหาที่แตกต่างกัน

สถานการณ์ทั่วไป

1

นักออกแบบสร้างแถบนำทางที่มี 5 ปุ่ม แต่ละปุ่มกว้าง 100 px — ดูดีบนภาษาอังกฤษ

2

การแปลภาษาเยอรมัน: 'Settings' เปลี่ยเป็น 'Einstellungen' (13 เทียบกับ 8 ตัวอักษร), 'Submit' เปลี่ยเป็น 'Absenden' (8 เทียบกับ 6 ตัวอักษร). แถบนำทางล้นออก.

3

ผลลัพธ์: บนอุปกรณ์มือถือ ปุ่มจะซ้อนทับกันหรือตัดข้อความ ทำให้การนำทางใช้งานไม่ได้สำหรับผู้ใช้ชาวเยอรมัน

ทำไมเรื่องนี้ถึงเป็นปัญหา

ทุกองค์ประกอบที่มีความกว้างคงที่เป็นจุดแตกหัก แอปทั่วไปมีปุ่มหลายร้อยปุ่ม ป้าย และการ์ดทั้งหมดต้องรองรับการขยายของข้อความ

คอนเทนเนอร์ที่มีความกว้างคงที่ (width: 120px) และปุ่มขนาดคงที่จะตัดออกหรือล้นเมื่อข้อความขยายออก CSS overflow: hidden จะซ่อนเนื้อหาอย่างเงียบๆ ในขณะที่ overflow: visible จะทำให้การจัดวางเสียหาย

ผู้ใช้เห็นป้ายชื่อถูกตัดทอนเช่น 'Einstellu...' แทน 'Einstellungen', หรือปุ่มทับซ้อนองค์ประกอบที่อยู่ติดกัน การดำเนินการที่สำคัญจะอ่านไม่ได้หรือติดคลิกไม่ได้

วิธีแก้

ออกแบบและนำเลย์เอาต์ยืดหยุ่นที่ปรับตามความยาวของเนื้อหาสำหรับทุก locale.

1

แทนที่ความกว้างคงที่ด้วย min-width, max-width และการจัดการแบบยืดหยุ่น ใช้ CSS Grid หรือ Flexbox เพื่อแจกสรรพื้นที่แบบไดนามิค

2

ตั้งค่าตัวคอนเทนต์ข้อความให้ขึ้นบรรทัด: ใช้ overflow-wrap: break-word และหลีกเลี่ยง white-space: nowrap สำหรับเนื้อหาที่สามารถแปลได้

3

ทดสอบ UI ของคุณด้วยการจำลองพหุภาษาแบบปลอมที่ยืดข้อความทั้งหมด 40% เพื่อจำลอง Worst Case — ก่อนที่คุณจะส่งข้อความไปยังนักแปล

ข้อผิดพลาด #5: การจัดรูปแบบวันที่และตัวเลข

ข้อมูลและตัวเลขดูเหมือนสากล แต่ 01/02/2025 หมายถึงวันที่ 2 มกราคมในสหรัฐอเมริกา และวันที่ 1 กุมภาพันธ์ในยุโรป เครื่องหมายจุลภาคและจุดทศนิยมเปลี่ยนความหมายของตัวเลข: 1,000.50 (สหรัฐอเมริกา) เทียบกับ 1.000,50 (เยอรมนี) การทำผิดพลาดทำให้เกิดความสับสน ข้อมูลผิดพลาด และความไม่ไว้วางใจ

['ไม่ฟอร์แมตข้อมูลหรือตัวเลขด้วยเทมเพลตสตริงด้วยตนเอง—ใช้ API ของ Intl เสมอ', 'เก็บข้อมูลทั้งหมดใน ISO 8601 และสกุลเงินในหน่วยที่เล็กที่สุด (เซนต์) ภายใน', 'ทดสอบด้วย Locales ที่ใช้สัญลักษณ์ทศนิยมต่างกัน ลำดับวันที่และระบบปฏิทินที่แตกต่างกัน']

อย่ากำหนดฟอร์แมตข้อมูลหรือจำนวนด้วยเทมเพลตสตริงด้วยตัวเอง — ใช้ Intl-APIs ตลอด

เก็บข้อมูลทั้งหมดใน ISO 8601 และสกุลเงินในหน่วยที่เล็กที่สุด (เซนต์) ภายในระบบ

ทดสอบกับ Locale ที่ใช้ตัวคั่นทศนิยมต่างกัน ลำดับวันที่และระบบปฏิทินที่แตกต่าง

สถานการณ์ทั่วไป

1

นักพัฒนารูปแบบวันที่เป็น MM/DD/YYYY และราคายัง $1,234.50 — ถูกต้องสำหรับผู้ใช้ชาวอเมริกัน.

2

ผู้ใช้ชาวเยอรมันเห็น 03/04/2025 และตีความว่าเป็น 3 เมษายน แทน 4 มีนาคม — การนัดหมายที่พลาดหรือการจองที่ผิดพลาด

3

ผลลัพธ์: ผู้ใช้จองเที่ยวบินในวันที่ไม่ถูกต้องและสงสัยเกี่ยวกับรูปแบบราคา ตั๋วสนับสนุนเพิ่มขึ้น 15% ในตลาดเยอรมนี

ทำไมเรื่องนี้ถึงเป็นปัญหา

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

สตริงฟอร์แมทที่ฮาร์ดโค้ด เช่น toLocaleDateString('en-US') หรือการจัดรูปแบบด้วย Template-Literals ละเว้น Locale ที่แท้จริงของผู้ใช้งาน แม้ Locale ถูกต้องแต่ระบบปฏิทินที่ผิด (Gregorian vs Hijri) ก็ทำให้เกิดปัญหา

ผู้ใช้อ่านข้อมูลผิดและป้อนข้อมูลในรูปแบบที่ผิด ผู้ใช้ในยุโรปที่เห็น 03/04/2025 อาจตีความว่านี่คือ 3 เมษายน แทน 4 มีนาคม — การนัดหมายที่พลาดหรือการจองที่ผิดพลาด

วิธีแก้ปัญหานี้

ใช้ API ของ Intl ที่มีอยู่ในระบบหรือไลบรารีที่รองรับ locale สำหรับวันที่ เวลา จำนวน และสกุลเงินทั้งหมด

1

แทนที่การจัดรูปแบบด้วยตนเองด้วย Intl.DateTimeFormat(locale) สำหรับวันที่ และ Intl.NumberFormat(locale, { style: 'currency', currency }) สำหรับราคา

2

เก็บข้อมูลในรูปแบบ ISO 8601 (YYYY-MM-DD) ภายในและฟอร์แมตเพื่อการแสดงผลด้วย Locale ของผู้ใช้

3

ทดสอบด้วย Locale ที่ใช้เครื่องหมายทศนิยมต่างกัน ลำดับวันที่แตกต่างกัน และระบบปฏิทินที่ต่างกัน

ข้อผิดพลาด #6: ลืมภาษา RTL

ภาษาเขียนจากขวาไปซ้าย (RTL) เช่น ภาษาอาหรับ ภาษาเฮบรู และเปอร์เซีย ถูกใช้งานโดยผู้คนมากกว่า 500 milyonคน อย่างไรก็ตาม แอปส่วนใหญ่ถูกออกแบบสำหรับการวางแนวจากซ้ายไปขวา (LTR) RTL-support ไม่ได้หมายถึงการกลับข้อความ — ทั้ง UI ต้องสะท้อน

['ตั้งแต่วันแรก ใช้คุณสมบัติ CSS ที่มีตรรกะเท่านั้น (inline-start/end, block-start/end)', 'ทดสอบแอปของคุณด้วย RTL (dir=rtl) บน HTML-Element ในทุกการทบทวนสปรินต์', 'สร้างรายการตรวจสอบ RTL สำหรับการนำทาง ไอคอน ฟอร์ม และตัวบ่งชี้ความคืบหน้า']

ตั้งแต่วันแรก ให้ใช้คุณสมบัติ CSS ที่สอดคล้องกับทิศทางตามภาษา (inline-start/end, block-start/end) เท่านั้น

ทดสอบแอปของคุณด้วย rtl บนองค์ประกอบ HTML ในทุกการทบทวนสปรินต์

สร้างรายการตรวจสอบ RTL สำหรับการนำทาง ไอคอน แบบฟอร์ม และการแสดงความก้าวหน้า

สถานการณ์ทั่วไป

1

นักพัฒนาซอฟต์แวร์ใช้ margin-left: 16px และ text-align: left ตลอดทั้งแอปพลิเคชัน — ปฏิบัติการ LTR มาตรฐาน

2

แอปเริ่มทำงานในซาอุดีอาระเบีย ปุ่มย้อนกลับชี้ไปข้างหน้า ช่องด้านข้างปรากฏที่ด้านที่ผิด และข้อมูลตัวเลขเรียงลำดับไม่ถูกต้อง

3

ผลลัพธ์: ผู้ใช้อาหรับออกจากแอปภายใน 30 วินาที ทีมต้องการ 4 สัปดาห์ในการ refactor CSS ด่วนเพื่อแก้ปัญหา

ทำไมเป็นปัญหา

การรองรับ RTL เกี่ยวข้องกับส่วนประกอบแต่ละส่วนของแอปพลิเคชัน การเพิ่ม RTL ภายหลังมักต้องเขียน CSS ใหม่ประมาณ 30-50% ของกฎทั้งหมด และตรวจสอบไอคอนและการออกแบบทุกส่วน

คุณสมบัติ CSS เช่น margin-left, padding-right, text-align: left และ float: left กำหนดทิศทางไว้ล่วงหน้า ไอคอนที่มีความหมายทางทิศทาง (ลูกศร, แถบความคืบหน้า) ชี้ไปในทิศทางที่ไม่ถูกต้อง ค่าขอบโค้ง (border-radius) ก็สะท้อนไปด้วย

ผู้ใช้ชาวอาหรับเห็นการนำทางในมุมที่ผิด กระบวนการความก้าวหน้าดำเนินไปทางทิศกลับ และข้อความที่ทับซ้อนกับส่วน UI แอปดูแปลกและใช้งานยาก

วิธีแก้ปัญหานี้

ใช้คุณสมบัติ CSS ที่มีตรรกะและทดสอบการออกแบบ RTLตั้งแต่ต้น

1

Tüm fiziksel CSS Özelliklerini mantıksal karşılıklarıyla değiştirin: margin-left → margin-inline-start, padding-right → padding-inline-end, text-align: left → text-align: start.

2

ตั้งค่า dir บน HTML-Root-Element ตาม Locale ที่ใช้งาน ใช้ pseudo-class CSS :dir(rtl) สำหรับ override RTL

3

ตรวจสอบไอคอนทั้งหมดว่ามีทิศทางหรือไม่ เปลี่ยนไอคอนที่มีทิศทางไปเป็นเวอร์ชันสะท้อนกลับ หรือใช้ CSS transform: scaleX(-1) ในบริบท RTL

ข้อผิดพลาด #7: รูปภาพที่มีข้อความ

การใส่ข้อความลงในภาพ — ไม่ว่าจะอยู่ใน Hero-Banner ปุ่ม อินโฟกราฟิก หรือภาพหน้าจอ — เป็นฝันร้ายในการ localization ภาพที่มีข้อความจะต้องสร้างใหม่สำหรับแต่ละภาษา ซึ่งจะทำให้ต้นทุนการออกแบบสูงขึ้นและปล่อยล่าช้า

['อย่านำข้อความที่สามารถแปลได้ไปฝังตรงๆ ในภาพราสเตอร์ (PNG, JPG)', 'ใช้ overlays ของข้อความ CSS บนภาพพื้นหลังสำหรับ Hero-Banner และ CTA', 'อัตโนมัติการสร้างภาพหน้าจอสำหรับ App Store รายการและหน้าเว็บไซต์การตลาด']

อย่าฝังข้อความที่สามารถแปลได้โดยตรงลงในภาพแรสเตอร์ (PNG, JPG)

ใช้ CSS Text Overlay บนภาพพื้นหลังสำหรับ Hero Banner และ CTAs

ทำให้การสร้างภาพหน้าจอสำหรับ App Store และหน้า Marketing อัตโนมัติ

กรณีทั่วไป

1

นักออกแบบสร้างแบนเนอร์โปรโมชั่นที่มีข้อความ 'Start Your Free Trial' ฝังอยู่ในภาพโดยตรง

2

ทีมท้องถิ่นแปลข้อความ UI ทั้งหมด แต่แบนเนอร์บนหน้าเยอรมันยังคงแสดงข้อความภาษาอังกฤษ

3

ผลลัพธ์: หน้าแลนด์ดิ้งของเยอรมันมีแบนเนอร์ภาษาอังกฤษที่ทำให้สับสน การสร้างแบนเนอร์ที่แปลเป็น 15 ภาษาใช้เวลาประมาณ 3 วันของงานออกแบบ และทำให้การเปิดตัวช้าลง

ทำไมเป็นปัญหา

หน้าเชิงการตลาดทั่วไปมีภาพที่มีข้อความ 5-10 ภาพ สำหรับ 15 ภาษา จะมีภาพที่แตกต่างกัน 75-150 แบบที่ต้องสร้าง ดูแล และอัปเดตเมื่อมีการออกแบบใหม่.

ข้อความที่ฝังอยู่ในภาพ (PNG, JPG, SVG ที่มีข้อความแนบอยู่) ไม่สามารถดึงออกได้ด้วยเครื่องมือแปล. เวอร์ชันที่แปลแล้วต้องให้ดีไซน์เนอร์แก้ไขไฟล์ต้นฉบับด้วยมือ, ส่งออก, และอัปโหลด

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

วิธีแก้ปัญหานี้

แยกข้อความออกจากภาพด้วย CSS overlays, SVG ที่มีองค์ประกอบข้อความที่สามารถแปลได้ หรือการสร้างภาพด้วยการสร้างภาพแบบไดนามิก

1

ใช้ CSS เพื่อวางข้อความที่สามารถแปลได้เหนือภาพพื้นหลัง: วางชั้นข้อความด้วยตำแหน่ง absolute เหนือคอนเทนเนอร์ภาพ

2

สำหรับอินโฟกราฟิกหรือตัวอย่างภาพ diagram ให้ใช้ SVG ที่มีองค์ประกอบข้อความ <text> ที่อ้างถึงคีย์การแปล แทนการฝังข้อความเปล่า

3

สำหรับภาพหน้าจอแอปในสื่อการตลาด ให้สร้างภาพหน้าจออัตโนมัติด้วยเครื่องมืออย่าง Fastlane (Mobile) หรือ Playwright (Web) ซึ่งจะถ่ายภาพหน้าจอในแต่ละ Locale

ข้อผิดพลาด #8: การขาดการแปลที่ยังไม่ได้รับการจัดการ

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

['ตรวจสอบให้แน่ใจเสมอว่ามีภาษา fallback อย่างน้อยหนึ่งภาษาในการตั้งค่า i18n ของคุณ', 'บันทึกคีย์การแปลที่ขาดหายไปในระบบมอนิเตอร์ของคุณเพื่อการติดตาม', 'กำหนดระดับการครอบคลุมการแปลขั้นต่ำก่อนที่ Locale จะเปิดใช้งาน']

กำหนดภาษา fallback อย่างน้อยหนึ่งภาษาในตั้งค่าการ i18n ของคุณ

บันทึกคีย์ที่ยังไม่มีการแปลไปยังระบบเฝ้าติดตามของคุณเพื่อให้ติดตามได้

กำหนดระดับการครอบคลุมการแปลขั้นต่ำ ก่อนที่ Locale จะเผยแพร่

กรณีทั่วไป

1

นักพัฒนาเพิ่มส่วนใหม่ 'Premium Features' ที่มี 15 คีย์การแปลใหม่ รุ่นภาษาอังกฤษถูกปล่อยออกมาทันที

2

การแปลภาษาฝรั่งเศสยังไม่เสร็จ หน้าภาษาฝรั่งเศสแสดงคีย์เปล่าๆ เช่น 'premium.feature1.title', 'premium.feature1.description'.

3

ผลลัพธ์: ผู้ใช้ภาษาฝรั่งเศสเห็นหน้าที่เสียหายเต็มไปด้วยชื่อคีย์ของนักพัฒนา ทีมสนับสนุมได้รับรายงานบัคหลายรายการ

ทำไมเรื่องนี้ถึงเป็นปัญหา

ยิ่งแอปของคุณใหญ่เท่าไร ช่องว่างระหว่างสตริงภาษาอังกฤษกับการแปลในภาษาอื่นก็ยิ่งใหญ่ขึ้น แอปที่มี 100 ภาษาและ 2,000 สตริงอาจมีการขาดการแปลมากกว่า 10,000 รายการอยู่เสมอ

Fallback-Lojik olmadan eksik çeviri anahtarları undefined, null ya da ham anahtar dizesini döndürebilir (ör. 'checkout.confirmButton'). Şablon motorları hatalar üretebilir, sayfa çöker ya da hiçbir şey render olmayabilir.

ผู้ใช้เห็น UI ที่เสียหาย: ปุ่มว่างเปล่า ไม่มีป้ายชื่อ หรือข้อความที่สับสนอย่าง 'nav.settings.title' แทนข้อความจริง นี่ทำให้สับสนและไม่เป็นมืออาชีพ

วิธีแก้ไข

ตั้งค่ากลุ่ม fallback ภาษาให้มั่นคง และติดตามการครอบคลุมการแปลในทุก locale

1

ตั้งค่าห่วงภาษา fallback ใน i18n ของคุณ: คีย์ภาษาฝรั่งเศส (fr) ที่หายไปจะตกกลับไปยังภาษาอังกฤษ (en) อย่างอัตโนมัติ

2

เพิ่มตัวจัดการ Missing-Key ที่บันทึกคีย์ที่ยังไม่ได้แปลไปยังระบบมอนิเตอร์ของคุณ (เช่น Sentry, Datadog) โดยไม่ทำให้ประสบการณ์ผู้ใช้เสียหาย

3

สร้างแดชบอร์ดความครอบคลุมการแปลที่ติดตามระดับความสมบูรณ์ต่อแต่ละ locale และบล็อกการเผยแพร่หากความครอบคลุมต่ำกว่าค่ากำหนด (เช่น 95%)

ข้อผิดพลาด #9: ปัญหาการเข้ารหัสอักขระ

ปัญหาการเข้ารหัสอักขระเป็น 'ฆาตกรเงียบ' ของการท้องถิ่น ทุกอย่างดูเรียบร้อยในภาษาอังกฤษและภาษาในยุโรป แต่เมื่อคุณเพิ่มภาษาจีน ญี่ปุ่น เกาหลี อารบิก หรือ Emoji จะพบ Mojibake ความผิดพลาดเหล่านี้มักตรวจจับยาก

['ใช้ UTF-8 ในทุกส่วน — ไฟล์ต้นฉบับ, ฐานข้อมูล, คำตอบ API และ HTML Meta-Tags', 'ใช้ utf8mb4 ใน MySQL (ไม่ใช่ utf8) เพื่อรองรับ Unicode ทั้งหมดรวมถึง Emoji', 'ทดสอบด้วยเนื้อหาจริงใน CJK, อารบิก และ Emoji เพื่อค้นหาปัญหาการเข้ารหัสตั้งแต่เนิ่นๆ']

ใช้การเข้ารหัส UTF-8 ทุกที่ — ไฟล์ต้นฉบับ ฐานข้อมูล คำตอบ API และ HTML-Meta-Tags

ใช้งาน utf8mb4 ใน MySQL (ไม่ใช่ utf8) เพื่อรองรับ Unicode ทั้งหมดรวมถึง Emoji

ทดสอบด้วยเนื้อหาจริงใน CJK ภาษาอารบิก และ Emoji เพื่อค้นหาปัญหาการเข้ารหัสล่วงหน้า

สถานการณ์ทั่วไป

1

นักพัฒนาระบบติดตั้งฐานข้อมูล MySQL ที่มีการเรียงลำดับ latin1 (มาตรฐานเก่า). โค้ดต้นฉบับของแอปพลิเคชันใช้ UTF-8

2

ผู้ใช้ชาวญี่ปุ่นลงทะเบียนด้วยชื่อจริงของพวกเขา ฐานข้อมูลจะบันทึก '田中太郎' เป็น bytes ที่เสียหาย

3

ผลลัพธ์: โปรไฟล์ผู้ใช้แสดงข้อความที่เพี้ยน. ที่แย่กว่านั้น: การค้นหาและการเรียงลำดับล้มเหลวสำหรับชื่อ CJK ซึ่งเกี่ยวข้องกับผู้ใช้นับพัน

ทำไมถึงเป็นปัญหานี้

ปัญหาการเข้ารหัสลายลักษณ์อักษรแพร่กระจายทั่วสแต็กของคุณ การตั้งค่าการจัดเรียงฐานข้อมูลผิดพลาดอาจทำให้ชุดข้อมูลหลายล้านแถวเสียหาย — การซ่อมแซมต้องมีการย้ายข้อมูลที่มีค่าใช้จ่ายสูง

การเข้ารหัสที่ไม่สอดคล้องกันในสแต็ก — UTF-8 ในไฟล์ต้นฉบับ, Latin-1 ในฐานข้อมูล และ Windows-1252 ในตอบ API — ทำลายสัญลักษณ์หลาย-byte. หนึ่งชั้นที่กำหนดค่าไม่ถูกต้องจะเปลี่ยน '日本語' เป็น '????' หรือ '日本èª'.

ผู้ใช้เห็นข้อความที่เพี้ยน เครื่องหมายคำถาม หรือช่องว่างที่ไม่แสดงภาษาเมื่อควรมีภาษา ในกรณีร้ายแรง การป้อนข้อมูลในแบบฟอร์มอาจเสียหายในฐานข้อมูล

วิธีแก้ไขปัญหานี้

บังคับให้เข้ารหัส UTF-8 สอดคล้องกันในทุกชั้นของ stack ของแอปพลิเคชัน

1

ตั้งค่าทุกไฟล์ต้นฉบับให้เป็น UTF-8 (ปรับโปรแกรมแก้แก้ของคุณและ .editorconfig) เพิ่ม <meta charset='UTF-8'> ใน HTML ของคุณ และ 'Content-Type: application/json; charset=utf-8' ในการตอบ API

2

กำหนดฐานข้อมูลของคุณให้ utf8mb4 (ไม่ใช่ utf8 เท่านั้น เนื่องจาก utf8 เป็นชุดอักษร 3 ไบต์ใน MySQL) ตั้งค่าการเรียงลำดับการเชื่อมต่อเป็น utf8mb4_unicode_ci

3

เลือกฟอนต์ที่ครอบคลุมระบบตัวอักษรเป้าหมายของคุณ: ลาติน, เคอร์ริลลิค, CJK, อารบิก, เดวานาการี. ใช้ System-Font-Stacks หรือ Google Fonts ที่มี subsets ตามภาษาเพื่อโหลดอย่างเหมาะสม

ทดสอบการใช้งาน i18n ของคุณ

การทดสอบการขยายความยาว

ขยายสตริงที่แปลทั้งหมด 30-40% เพื่อจำลองการขยายข้อความที่เกิดในภาษาอย่างเยอรมัน ฟินแลนด์ หรือกรีก ซึ่งมีคำที่ยาวขึ้น และครอบคลุม container ที่มีความกว้างคงที่ ป้ายที่ถูกตัด และปุ่มที่ล้นก่อนที่คุณจะเริ่มแปลจริง เครื่องมือ pseudo-localization หลายตัวมีฟีเจอร์นี้ในตัว

"Senden" → "Ṡééééñðéñ_éxpáñðéð" (ยาวขึ้น 40%)

โลคัลไลเซชันเทียม

การโลคาลิไซด์ปลอมจะเปลี่ยนทุกตัวอักษรให้เป็นสำเนียงที่มีเครื่องหมาย (เช่น 'a' → 'á') และหุ้มข้อความด้วยเครื่องหมายอย่าง [!! และ !!]. ด้วยวิธีนี้จะเห็นได้ทันทีว่าอักษรใดถูก hard-code และอันไหนมาจากระบบการแปล. รันโลคาลิไซชันปลอมเป็นส่วนหนึ่งของ pipeline CI ของคุณเพื่อจับ regression อัตโนมัติ.

ข้อความบนหน้าจอทั้งหมดที่ไม่ถูกห่ออยู่ใน [!! !!]-เครื่องหมายจะถูกฝังไว้ในโค้ดและต้องถูกแยกออก การทดสอบนี้จะจับประมาณ 95% ของสตริงที่ถูกมองข้ามในเวลาน้อยกว่า 1 นาที

"ส่งข้อความ" → "[!! Ñáçḥŕíçḥṫ ṡéñðéñ !!]"

การทดสอบการออกแบบ RTL

แม้จะไม่มีการแปลภาษาอาหรับหรือฮีบรู คุณยังสามารถทดสอบ RTL-layout โดยการเพิ่ม dir='rtl' ให้กับ HTML root ของคุณ นี่จะเปิดเผยบั๊ก CSS ที่เกี่ยวกับทิศทางทันที: ไอคอนจัดตำแหน่งไม่ถูก, ช่องว่างด้านขวา/ซ้ายผิด, การนำทางทำงานผิด และรายการ Flex เรียงลำดับผิด ทำให้เป็นการตรวจสอบมาตรฐานในทุก Sprint Review — ใช้เวลา 10 วินาทีในการสลับและจับปัญหาที่อาจต้องใช้สัปดาห์ในการแก้ใน Production.

รายการตรวจสอบ i18n

['ข้อความทั้งหมดที่มองเห็นได้ของผู้ใช้ถูกย้ายไปยังไฟล์ทรัพยากร', 'ไม่ใช้การต่อสตริงเพื่อสร้างประโยค', 'ได้ดำเนินการกติกาพหูพจน์ด้วย ICU MessageFormat หรือเทียบเท่า', 'การจัดรูปแบบวันที่ เวลา และตัวเลขโดยใช้ API ที่คำนึงถึง Locale', 'ทดสอบการออกแบบ RTL ด้วยเนื้อหาภาษาอาหรับหรือฮีบรู', 'UI ที่ยืดหยุ่นโดยไม่กำหนดความกว้างคงที่สำหรับองค์ประกอบที่มีข้อความ', 'กำหนดภาษากลับและทดสอบเมื่อคีย์ขาดหาย', 'การเข้ารหัส UTF-8 สอดคล้องกันในทุกไฟล์และฐานข้อมูล', 'เมตาดาต้าของ App Store และ Play Store สำหรับแต่ละตลาดถูกท้องถิ่น', 'ภาพหน้าจอและทรัพยากรการตลาดสำหรับแต่ละภาษาถูกอัปเดต']

แชร์บทความ

พร้อมที่จะแปลแอปของคุณหรือยัง?

แปลแอป iOS, Android หรือเว็บของคุณเป็นมากกว่า 29 ภาษา ด้วยการแปลด้วย AI

เริ่มใช้งานฟรี

เนื้อหาที่เกี่ยวข้อง

คู่มือ

เลือกภาษาสำหรับแอปของคุณ

คู่มือบนพื้นฐานข้อมูลสำหรับการเลือกภาษาที่เหมาะสมสำหรับการแปลแอป เรียนรู้ว่าภาษาใดให้ ROI ที่ดีที่สุด — อิงจากขนาดตลาด, ARPU และการแข่งขัน

7 min
target languagesmarket researchlocalization strategy