
การขยายข้อความใน i18n : ป้องกันเลย์เอาต์เสียหายจากความยาวคำแปล
UI ภาษาอังกฤษของคุณพอดีอย่างสมบูรณ์แบบ แต่เมื่อคำแปลภาษาเยอรมันมาถึงกลับยาวขึ้น 30% ส่วนภาษาฟินแลนด์ยาวขึ้น 40% ปุ่มล้น ตารางเสีย และเลย์เอาต์ที่ออกแบบอย่างประณีตพังลง การทดสอบการขยายข้อความป้องกันปัญหานี้ได้
เหตุใดการขยายข้อความจึงทำให้เลย์เอาต์เสียหาย
นักพัฒนาออกแบบ UI ด้วยข้อความภาษาอังกฤษซึ่งเป็นหนึ่งในภาษาที่กระชับที่สุด เมื่อคำแปลมาถึง ภาษาที่ใช้ข้อความยาวกว่าจะล้นคอนเทนเนอร์ ทำเลย์เอาต์กริดเสีย ตัดป้ายปุ่ม และดันเนื้อหาออกนอกหน้าจอ บั๊กเหล่านี้ปรากฏเฉพาะในบางภาษา จึงมองไม่เห็นระหว่างการพัฒนาและทดสอบด้วยภาษาอังกฤษเพียงภาษาเดียว
// English is one of the most compact languages.
// Translations are almost always LONGER.
// English (source):
"Save" // 4 chars
// Translations:
"Speichern" // German: 10 chars (+150%)
"Enregistrer" // French: 12 chars (+200%)
"Guardar" // Spanish: 7 chars (+75%)
"Сохранить" // Russian: 9 chars (+125%)
"Tallenna" // Finnish: 8 chars (+100%)
// Buttons, labels, and table headers designed for
// English text WILL break in other languages.อัตราการขยายข้อความตามภาษา
อัตราการขยายเฉลี่ยเมื่อเทียบกับข้อความต้นฉบับภาษาอังกฤษ ข้อความสั้น (ไม่เกิน 20 อักขระ) ขยายมากกว่าข้อความยาว เพราะการเลือกแต่ละคำส่งผลต่อความยาวรวมมากกว่า
// Average text expansion relative to English:
// European languages:
// German: +30-35% (compound words)
// Finnish: +30-40% (agglutinative)
// French: +15-25% (articles, prepositions)
// Spanish: +15-25%
// Italian: +15-25%
// Portuguese: +15-25%
// Russian: +20-30% (case endings)
// Polish: +20-30%
// Greek: +20-30%
// Asian languages (CJK):
// Chinese: -30-50% (shorter in characters, but wider per char)
// Japanese: -20-40% (kanji compress meaning)
// Korean: -10-20%
// Right-to-left:
// Arabic: +20-30%
// Hebrew: +10-20%
// Rule of thumb by source string length:
// 1-10 chars: expect +200% expansion
// 11-20 chars: expect +80% expansion
// 21-70 chars: expect +40% expansion
// 71+ chars: expect +30% expansionการทดสอบด้วย i18n-pseudo
กลยุทธ์การขยายของ i18n-pseudo เติมข้อความต้นฉบับให้ยาวขึ้นเพื่อจำลองความยาวคำแปล ตั้งอัตราการขยายให้ตรงกับภาษาเป้าหมาย แล้วทดสอบเลย์เอาต์ก่อนมีคำแปลจริง
# Method 1: Pseudo-localization with expansion
npx i18n-pseudo generate \
--source locales/en.json \
--output locales/pseudo-expanded.json \
--expansion 1.4 \
--preset expanded
# Method 2: Longest-translation analysis
npx i18n-validate expansion \
--source locales/en.json \
--targets 'locales/*.json' \
--report expansion-report.json
# Output:
# Key | EN | Longest | Lang | Ratio
# ---------------------|-----|---------|------|-------
# nav.settings | 8 | 14 | de | 175%
# buttons.save | 4 | 12 | fr | 300%
# errors.networkFailed | 14 | 28 | fi | 200%
# Method 3: Visual regression with expanded text
npx playwright test \
--project=expansion-test \
--update-snapshots// playwright.config.ts
export default defineConfig({
projects: [
{
name: 'expansion-test',
use: {
locale: 'pseudo-expanded',
},
},
],
});
// tests/expansion.spec.ts
test('buttons do not overflow with expanded text', async ({ page }) => {
await page.goto('/');
// Check no horizontal overflow
const buttons = await page.locator('button').all();
for (const button of buttons) {
const box = await button.boundingBox();
const parent = await button.locator('..').boundingBox();
expect(box!.x + box!.width).toBeLessThanOrEqual(
parent!.x + parent!.width
);
}
// Visual snapshot comparison
await expect(page).toHaveScreenshot('homepage-expanded.png', {
maxDiffPixels: 100,
});
});แนวทางปฏิบัติด้านการออกแบบสำหรับ i18n
การสร้างเลย์เอาต์ให้รองรับการขยายข้อความต้องตัดสินใจด้านการออกแบบก่อนเริ่มงานแปล แนวทางเหล่านี้ช่วยป้องกันบั๊กที่เกี่ยวข้องกับการขยายซึ่งพบบ่อยที่สุด
/* 1. Use flexible containers, not fixed widths */
/* WRONG */
.button { width: 120px; }
/* RIGHT */
.button { min-width: 80px; padding: 8px 16px; }
/* 2. Allow text wrapping in labels */
/* WRONG */
.label { white-space: nowrap; overflow: hidden; }
/* RIGHT */
.label { overflow-wrap: break-word; }
/* 3. Use CSS Grid/Flexbox for adaptive layouts */
.nav {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
/* 4. Reserve space for the longest expected translation */
/* Use min-width based on ~1.4x English length */
.table-header {
min-width: max-content;
padding-right: 16px;
}
/* 5. Test with the longest language first */
/* German and Finnish are good stress-test languages */
/* 6. For CJK: account for wider characters */
/* CJK characters are typically 2x the width of Latin chars */
/* Even though text is shorter, it may be wider visually */ลองใช้ i18n Agent ตอนนี้
ลากและวางไฟล์แปลของคุณที่นี่
JSON, YAML, PO, XML, CSV, Markdown, Properties
หรือคลิกเพื่อเลือกไฟล์
ภาษาเป้าหมาย