Skip to main content

SvelteKit i18n:国際化設定ガイド

ゼロから多言語対応まで、ICU メッセージ形式、ロケールベースのルーティング、高度なフォールバックチェーンを使用して、SvelteKit アプリに svelte-i18n を設定します。

1

svelte-i18n のインストール

svelte-i18n は、Svelte と SvelteKit の標準的な国際化ライブラリです。リアクティブストア、ICU MessageFormat、ロケールの遅延読み込みを標準で提供します。

svelte-i18n は、複数形と変数に FormatJS/react-intl と同じ標準規格である ICU MessageFormat を使用します。React の経験があれば、メッセージ構文にも馴染みやすいでしょう。
Terminal
npm install svelte-i18n
2

svelte-i18n の設定

遅延読み込み用の import 関数とともにロケールを登録する i18n 設定ファイルを作成します。svelte-i18n は、ロケールが有効になったときにのみ、そのロケールのメッセージを取得します。

src/lib/i18n.ts
// src/lib/i18n.ts
import { register, init, getLocaleFromNavigator } from 'svelte-i18n';

// Register locale loaders (lazy-loaded)
register('en', () => import('../locales/en.json'));
register('de', () => import('../locales/de.json'));
register('ja', () => import('../locales/ja.json'));
register('es', () => import('../locales/es.json'));

init({
  fallbackLocale: 'en',
  initialLocale: getLocaleFromNavigator(),  // Auto-detect browser language
});
コンポーネントがレンダリングされる前に、+layout.svelte で i18n 設定ファイルを import する必要があります。翻訳が「nav.home」のような未変換のキーで表示される場合、設定ファイルの import が遅すぎます。

SvelteKit レイアウトへの統合

ルートレイアウトで i18n 設定を import し、$isLoading ストアでレンダリングを制御します。ロケールデータを非同期で読み込んでいる間に未翻訳キーが一瞬表示されることを防げます。

src/routes/+layout.svelte
<!-- src/routes/+layout.svelte -->
<script>
  // Import i18n config — must run before any component renders
  import '../lib/i18n';
  import { isLoading } from 'svelte-i18n';
</script>

{#if $isLoading}
  <p>Loading translations...</p>
{:else}
  <slot />
{/if}

SvelteKit のロケールベースルーティング

/en/about や /de/about のような SEO に配慮した URL には、[lang] ルートパラメーターを使用します。URL パラメーターに基づき、レイアウトの load 関数で svelte-i18n のロケールを設定してください。

SvelteKit locale routing
// src/routes/[lang]/+layout.ts
import { locale } from 'svelte-i18n';

export function load({ params }) {
  // Set the active locale from the URL parameter
  locale.set(params.lang);
  return {};
}

// src/routes/[lang]/+layout.svelte
<script>
  import '../../lib/i18n';
  import { isLoading } from 'svelte-i18n';
</script>

{#if $isLoading}
  <p>Loading...</p>
{:else}
  <slot />
{/if}

翻訳ファイル形式

ロケールごとに JSON ファイルを 1 つ作成します。svelte-i18n は、ネストしたキーと、複数形、変数、select 式に対応する ICU MessageFormat 構文をサポートしています。

Translation files
// src/locales/en.json
{
  "nav": {
    "home": "Home",
    "about": "About",
    "settings": "Settings"
  },
  "greeting": "Hello, {name}!",
  "cart": {
    "itemCount": "{count, plural, one {# item} other {# items}}"
  }
}

// src/locales/de.json
{
  "nav": {
    "home": "Startseite",
    "about": "Uber uns",
    "settings": "Einstellungen"
  },
  "greeting": "Hallo, {name}!",
  "cart": {
    "itemCount": "{count, plural, one {# Artikel} other {# Artikel}}"
  }
}
キー名は表示場所ではなく、内容に基づいて付けてください。「homepageCartLabel」より「cart.itemCount」が適切です。UI を再設計しても維持できるキーにします。
3

コンポーネントでの翻訳の使用

svelte-i18n から $_ ストア(または $format)を import し、Svelte テンプレートで使用します。ストアはリアクティブであるため、ロケールが変わると、すべての翻訳文字列が自動的に更新されます。

Component.svelte
<script>
  import { _ } from 'svelte-i18n';
</script>

<h1>{$_('greeting', { values: { name: 'World' } })}</h1>

<nav>
  <a href="/">{$_('nav.home')}</a>
  <a href="/about">{$_('nav.about')}</a>
</nav>
Formatting helpers
<script>
  import { _, date, number, time } from 'svelte-i18n';
</script>

<!-- Simple string -->
<p>{$_('greeting', { values: { name: userName } })}</p>

<!-- ICU plurals — handled automatically -->
<p>{$_('cart.itemCount', { values: { count: 3 } })}</p>

<!-- Date formatting -->
<p>{$date(new Date(), { format: 'long' })}</p>

<!-- Number formatting -->
<p>{$number(1999.99, { style: 'currency', currency: 'USD' })}</p>
$_ は Svelte ストアであるため、テンプレートでは $ プレフィックスが必要です。ドル記号なしで _('key') と記述すると、翻訳文字列ではなくストアオブジェクトが返されます。

言語の切り替え

$locale ストアにバインドする言語セレクターを作成します。値が変わると、svelte-i18n が新しいロケールのメッセージを読み込み、すべての翻訳文字列をリアクティブに更新します。

LanguageSwitcher.svelte
<script>
  import { locale, locales } from 'svelte-i18n';

  const LANGUAGE_NAMES = {
    en: 'English',
    de: 'Deutsch',
    ja: '日本語',
    es: 'Espanol',
  };
</script>

<select bind:value={$locale}>
  {#each $locales as loc}
    <option value={loc}>{LANGUAGE_NAMES[loc] ?? loc}</option>
  {/each}
</select>
4

ICU MessageFormat による複数形処理

svelte-i18n は、CLDR のすべての複数形カテゴリーを処理する国際標準 ICU MessageFormat を複数形に使用します。アラビア語は 6 形式、ロシア語は 4 形式、日本語は 1 形式です。対象言語に必要な形式を定義すると、svelte-i18n が正しい形式を自動的に選択します。

ICU plural forms by language
// svelte-i18n uses ICU MessageFormat for plurals
// English:
{
  "items": "{count, plural, one {# item} other {# items}}"
}

// Arabic (6 forms):
{
  "items": "{count, plural, zero {no items} one {item} two {two items} few {# items} many {# items} other {# items}}"
}

// Japanese (1 form):
{
  "items": "{count, plural, other {#個のアイテム}}"
}
コンポーネントに単数形・複数形のロジックをハードコードしないでください。フランス語では 0 を単数として扱います。また、アラビア語、ロシア語、ポーランド語には英語にない複数形があります。ICU の複数形構文に処理を任せてください。

svelte-i18n-locale-chain による高度なロケールフォールバック

svelte-i18n はキーがない場合に fallbackLocale へ直接フォールバックし、中間のフォールバックを行いません。そのため、pt-BR のユーザーには適切な pt-PT 翻訳があっても英語が表示されます。svelte-i18n-locale-chain は、地域バリエーションのメッセージをディープマージする高度なフォールバックチェーンで、この問題を解決します。

Terminal
npm install svelte-i18n-locale-chain svelte-i18n
src/lib/i18n.ts
// src/lib/i18n.ts
import { initLocaleChain, setLocale } from 'svelte-i18n-locale-chain';

// Replace svelte-i18n's init + register with initLocaleChain
await initLocaleChain({
  loadMessages: (locale) =>
    import(`../locales/${locale}.json`).then(m => m.default),
  defaultLocale: 'en',
  initialLocale: 'pt-BR',
});

// Later, to change locale:
await setLocale('fr-CA');
// fr-CA user sees: fr-CA messages -> fr messages -> en messages
// No missing keys — deep-merged automatically
svelte-i18n-locale-chain は、すべてのメッセージ読み込みを内部で管理します。svelte-i18n の register() 関数を併用しないでください。initLocaleChain が登録、読み込み、ディープマージを処理します。

翻訳の自動化

i18n の設定が完了したら、AI を使用してロケールファイルを翻訳します。IDE で AI アシスタントにソースファイルの翻訳を依頼するか、CI/CD パイプラインで i18n Agent CLI を使用できます。

Terminal
# In your IDE, ask your AI assistant:
> Translate src/locales/en.json to German, Japanese, and Spanish

✓ de.json created (1.2s)
✓ ja.json created (1.5s)
✓ es.json created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate src/locales/en.json --lang de,ja,es
差分単位で翻訳してください。ソースファイルに新しいキーを追加した場合は、すべてのファイルを再生成せず、差分だけを翻訳します。人が確認済みの翻訳を保持できます。

翻訳品質の自動管理

i18n-validate を使用すると、リリース前に欠落キーや壊れたプレースホルダーを検出できます。実際の翻訳が届く前に、i18n-pseudo の疑似翻訳で UI をテストしてください。

よくある問題

SvelteKit で SSR ロケールが混在する

svelte-i18n ストアはシングルトンです。SvelteKit SSR では同時リクエストが同じストアを共有するため、あるユーザーのロケールが別のユーザーへのレスポンスに混入する場合があります。対処方法として、handle フックまたはレイアウトの load 関数で locale.set() を呼び出し、各リクエストに正しいロケールコンテキストを設定してください。

svelte-i18n-locale-chain と register() を併用する

svelte-i18n-locale-chain を使用する場合、svelte-i18n の register() 関数は使用しないでください。initLocaleChain がすべてのメッセージ読み込みを内部で処理します。両方を併用すると、メッセージが重複して読み込まれたり、競合したりします。

ICU 構文エラーが通知されない

ICU MessageFormat 文字列で波括弧が対応していなかったり、複数形カテゴリーが欠けていたりすると、エラー通知なしで失敗し、書式設定済みの出力ではなく未処理のメッセージ文字列が表示されます。CI パイプラインで ICU 構文を検証してください。

未翻訳コンテンツが一瞬表示される

翻訳の読み込みが完了する前にコンポーネントをレンダリングすると、未変換のキーが表示されます。レイアウトを {#if $isLoading}...{:else}...{/if} で制御し、メッセージの準備が整うまで読み込み状態を表示してください。

推奨ファイル構成

Project Structure
my-sveltekit-app/
├── src/
│   ├── lib/
│   │   └── i18n.ts              # i18n configuration
│   ├── locales/
│   │   ├── en.json              # Source language
│   │   ├── de.json              # German
│   │   ├── ja.json              # Japanese
│   │   └── es.json              # Spanish
│   └── routes/
│       ├── +layout.svelte       # Import i18n, guard isLoading
│       ├── +page.svelte
│       └── [lang]/              # Optional: locale-based routing
│           ├── +layout.ts       # Set locale from URL param
│           ├── +layout.svelte
│           └── +page.svelte
├── svelte.config.js
└── package.json

i18n Agent を今すぐ試す

翻訳ファイルをここにドロップ

JSON, YAML, PO, XML, CSV, Markdown, Properties

またはクリックしてファイルを選択

翻訳先言語

登録不要すぐに見積もり

svelte-i18n-locale-chain によるロケールフォールバック

pt-BR のような地域ロケールに翻訳キーがない場合、svelte-i18n は親ロケール pt を先に確認せず、デフォルトロケールへ直接フォールバックします。

Terminal
npm install svelte-i18n-locale-chain
Configuration
import { initLocaleChain } from 'svelte-i18n-locale-chain';

initLocaleChain({
  fallbacks: {
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
  },
  defaultLocale: 'en',
});

対応フレームワークの全一覧と 75 の組み込みチェーンについては、ロケールフォールバックガイドをご覧ください。 Learn more →

よくある質問