Skip to main content

i18n 텍스트 확장: 번역 길이로 인한 레이아웃 손상 방지

영어 UI에는 완벽하게 맞았는데 독일어 번역은 30% 더 길고 핀란드어 번역은 40% 더 길어요. 버튼이 넘치고 표가 깨지며 공들여 만든 레이아웃이 무너져요. 텍스트 확장 테스트로 이를 예방하세요.

1

텍스트 확장이 레이아웃을 망가뜨리는 이유

개발자는 가장 간결한 언어 중 하나인 영어 텍스트로 UI를 디자인해요. 번역문이 길어지면 컨테이너 밖으로 넘치고 그리드 레이아웃이 깨지며 버튼 레이블이 잘리고 콘텐츠가 화면 밖으로 밀려나요. 이런 버그는 특정 로케일에서만 나타나므로 영어로만 개발하고 테스트할 때는 보이지 않아요.

The expansion problem
// 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.
텍스트 확장은 드문 예외가 아니에요. 여러 언어를 지원하는 모든 UI에서 발생해요. 독일어는 영어보다 30% 더 길고 핀란드어는 40% 더 길며 일부 언어는 짧은 문자열에서 100% 이상 더 길어질 수 있어요. 번역이 오기 전에 확장을 테스트하면 비용이 많이 드는 재설계를 막을 수 있어요.
2

언어별 텍스트 확장 비율

영어 원문을 기준으로 한 평균 확장 비율이에요. 20자 미만인 짧은 문자열은 개별 단어 선택이 전체 길이에 미치는 영향이 더 커서 긴 문자열보다 많이 확장돼요.

Expansion ratios by language
// 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
평균값일 뿐이에요. 개별 문자열은 훨씬 더 길어질 수 있어요. 영어로 두 단어인 버튼 레이블이 독일어에서 네 단어가 될 수도 있어요. 버튼, 탐색, 표 머리글 같은 중요한 UI 요소는 더 높은 비율(50% 이상)로 테스트하세요.
3

i18n-pseudo로 테스트

i18n-pseudo의 확장 전략은 번역 길이를 모방하도록 원본 문자열에 패딩을 추가해요. 대상 언어에 맞게 확장 비율을 설정하고 실제 번역이 오기 전에 레이아웃을 테스트하세요.

Terminal
# 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
Visual regression tests
// 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,
  });
});
유럽 언어에는 40%, 최악의 상황에는 50% 확장으로 테스트하세요. 레이아웃이 50% 확장을 견디면 거의 모든 언어를 처리할 수 있어요.
4

i18n 디자인 모범 사례

텍스트 확장을 처리하는 레이아웃을 만들려면 번역 작업이 시작되기 전에 디자인 결정을 내려야 해요. 다음 원칙을 따르면 가장 흔한 확장 관련 버그를 예방할 수 있어요.

CSS best practices
/* 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

또는 클릭하여 파일 선택

대상 언어

가입 불필요즉시 견적

텍스트 확장 FAQ