
Rozšíření textu v i18n: Zabraňte rozbití rozložení kvůli délce překladu
Vaše anglické UI perfektně sedí. Pak přijdou německé překlady — o 30 % delší. Finština je o 40 % delší. Tlačítka přetékají, tabulky se rozbíjejí a pečlivě navržené rozložení se rozpadá. Tomu předchází testování rozšíření textu.
Proč rozšíření textu rozbíjí rozložení
Vývojáři navrhují UI s anglickým textem, který je jedním z nejkompaktnějších jazyků. Když dorazí překlady, delší jazyky přetékají kontejnery, rozbíjejí rozložení mřížky, zkracují popisky tlačítek a vytlačují obsah mimo obrazovku. Tyto chyby se objevují jen v konkrétních locale, takže jsou při vývoji a testování pouze v angličtině neviditelné.
// 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.Poměry rozšíření textu podle jazyka
Průměrné poměry rozšíření vůči anglickému zdrojovému textu. Krátké řetězce (pod 20 znaků) se rozšiřují více než dlouhé řetězce, protože volba jednotlivých slov má větší dopad na celkovou délku.
// 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% expansionTestování s i18n-pseudo
Strategie rozšíření v i18n-pseudo přidává ke zdrojovým řetězcům vycpávku, aby simulovala délku překladu. Nastavte poměr rozšíření tak, aby odpovídal Vašim cílovým jazykům, a otestujte rozložení ještě předtím, než dorazí skutečné překlady.
# 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,
});
});Designové osvědčené postupy pro i18n
Vytváření rozložení, která zvládnou rozšíření textu, vyžaduje designová rozhodnutí udělaná ještě předtím, než začne překlad. Tyto postupy předcházejí nejběžnějším chybám souvisejícím s rozšířením.
/* 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 */Vyzkoušejte i18n Agent nyní
Sem přetáhněte svůj překladový soubor
JSON, YAML, PO, XML, CSV, Markdown, Properties
nebo klikněte a vyberte soubor
Cílové jazyky