Ovellum v0.12.0
日本語

最終更新

多言語対応(i18n)#

Ovellum は同じサイトを複数の言語で公開できます。これはオプトインです。単一言語のサイトはロケールフォルダを必要とせず、これまでとまったく同じように動作します。言語を宣言してオンにすると、コンテンツは言語ごとに 1 つのサブツリーへ移動します。

有効にする#

config に site.locales(および必要に応じて site.defaultLocale)を追加します。

export default {
  site: {
    defaultLocale: 'en-US',
    locales: [
      { code: 'en-US', label: 'English' },
      { code: 'ja', label: '日本語' },
      { code: 'zh-Hans', label: '简体中文' },
    ],
  },
} satisfies OvellumUserConfig;
  • codeBCP 47 の言語タグです — en-USjazh-Hans / zh-Hantdept-BR。これはコンテンツフォルダ名であり、<html lang> でもあります。
  • label はピッカーが表示するものです — その言語の自称(その言語自身の名前: 日本語简体中文English)を使ってください。読者は自分の言語をその固有の文字体系で探すからです。
  • defaultLocale はサイトのルートで配信されます。デフォルトは locales の最初のエントリです。

正しいコードを使ってください。イギリス英語は en-GBen-uk ではない)、日本語は jajp ではない)、中国語は国コードではなくスクリプトサブタグ — zh-Hans(簡体字)または zh-Hant(繁体字)— を使います。

ロケールごとにコンテンツを整理する#

ロケールをオンにすると、コンテンツは言語ごとに 1 つのサブツリーへ、そのコードを名前として配置されます。

content/
  public/              ← shared across all locales (copied to the root)
  en-US/               ← the default locale
    _landing.md
    docs/
      getting-started.md
      guides/install.md
  ja/                  ← Japanese
    docs/
      getting-started.md

ページは同一の相対パスによって言語間で対応します。en-US/docs/guides/install.mdja/docs/guides/install.md の翻訳です。このマッピングを言語ピッカーが追います。各ロケールは独自のサイドバー、_meta.json の順序、フロントマターを持ちます。

予約された publicDirpublic/)は共有のままです — これはロケールではなく、出力ルートに一度だけコピーされます。

既存サイトの移行#

単一言語のサイトに i18n を追加するのは、一度きりの移動です。既存のコンテンツを content/<defaultLocale>/ に入れ、locales の config を追加します。コンテンツのルートにあったファイル(たとえば CNAME)は public/ に移し、引き続き出力ルートに届くようにします。ほかには何も変わりません。

URL#

デフォルトロケールはルートで配信され、それ以外のロケールはすべてそのコードの下で配信されます。

ページen-US(デフォルト)ja
docs/guides/install.md/docs/guides/install//ja/docs/guides/install/
ホーム / ランディング//ja/

なので、デフォルトロケールがすでに使っていた言語であれば、既存の URL は変わりません。

言語ピッカー#

トップバー(ナビリンクの後、アイコンクラスターの前)にグローブのドロップダウンが現れ、すべてのロケールをそのラベルで一覧表示します。切り替えると、読者はその言語の同じページに移動します。ページがまだ翻訳されていない場合、ピッカーはそのロケールのホームにフォールバックします — だから、わずかなページだけを翻訳した状態で言語を出荷し、時間をかけて育てていくことができます。

各ページには <html lang> も付き、site.baseUrl が設定されているときは hreflang の alternate リンク(およびデフォルトロケール用の x-default)も付くので、検索エンジンが正しい言語を配信します。

何がローカライズされ、何がまだされていないか#

ローカライズされる: すべてのページコンテンツとフロントマター、サイドバー/ナビ、ページ URL、<html lang>、hreflang、サイトマップ、そしてテンプレート自身の UI クロム — 「このページの内容」、「最終更新」とその日付、「分で読めます」、外観パネルのラベル、前後リンク、404 ページなど。クロムは組み込みの言語セット(現在は英語と日本語)向けに翻訳済みで出荷されます。それ以外のロケールは文字列ごとに英語へフォールバックし、不足分は自分で埋められます(下記参照)。右から左に書く言語には <html dir="rtl"> も自動的に付きます。

config 由来のテキスト — ovellum.config.* に書くランディングのヒーロー/CTA/機能のコピーや、topbarNav / footerNav のリンクラベル — もローカライズできます。これらのフィールドは、プレーンな文字列か、ロケールごとのマップ(下記)のどちらかを受け取ります。

まだされていない: ロケールごとの RSS フィード。

config テキストをローカライズする#

config がユーザー向けのラベルやコピー文字列を受け取る箇所では、プレーンな文字列の代わりにロケールごとのマップを渡せます — ロケール code をキーにし、デフォルトロケールにフォールバックします:

topbarNav: [{ label: { 'en-US': 'Docs', ja: 'ドキュメント' }, href: '/docs/' }],
landing: {
  hero: {
    title: { 'en-US': "Docs that don't drift.", ja: 'ドリフトしないドキュメント。' },
    ctas: [{ label: { 'en-US': 'Get started', ja: 'はじめる' }, href: '/docs/' }],
  },
},

プレーンな文字列も引き続き使え、すべてのロケールで表示されます — なので、実際に翻訳する文字列だけをマップ化すればよいのです。対象は topbarNav/footerNav のラベルと、ランディングのヒーロータイトル/サブタイトル、CTA ラベル、機能のタイトル/説明、install のタイトル、トラストストリップのテキストです。

クロム文字列を上書き・追加する#

組み込みにないロケールや、別の言い回しにしたい場合は、ロケールに strings を設定します — 組み込みテーブルの上にマージされます(省略した分は英語が埋めます):

site: {
  locales: [
    { code: 'en-US', label: 'English' },
    {
      code: 'fr',
      label: 'Français',
      strings: { tocTitle: 'Sur cette page', editedLabel: 'Modifié', backToTop: 'Haut de page' },
    },
  ],
}

キーは UI 文字列の名前(tocTitleeditedLabelminReadpreviousnextbackToTop、外観パネルのラベルなど)です。

翻訳はあなたが書くか生成するもの#

Ovellum は各ロケールフォルダにある Markdown をそのままレンダリングします。手作業で翻訳を書いても、好きな方法で事前翻訳してファイルを置いても構いません — ツールはあなたの代わりに翻訳することはなく、邪魔もしません。

翻訳を同期させ続ける#

手作業で維持する翻訳の難しさは、書くことではありません — **元(ソース)**のページが変わったのに翻訳が気づかぬうちに遅れていく、それに気づくことです。ovellum check はそのドリフトを見張ります。

各翻訳ページは、フロントマターに sourceHash を持てます — それがミラーするデフォルトロケールのページの指紋です(ロケールフォルダをまたいで同一のパスで対応づけられます。例: ja/docs/install.mden-US/docs/install.md)。check はソースの指紋を再計算して比較します:

  • ソースが変わっていない → 何も報告しません。
  • スタンプ後にソースが変わった[i18n] として stale(古い)と報告します(終了コード 1。CI が検知できます)。
  • まだ sourceHash がない → 報告します。新しい翻訳がスタンプされるようにするためです。
  • 対応するソースページがない → orphan(みなしご)翻訳として報告します。

ハッシュを手で書く必要はありません。翻訳をソースに合わせ直したら、スタンプします:

ovellum check --update-translations

これは各翻訳ページに現在の sourceHash を書き込み(変更するのはそのフロントマター 1 行だけ)、終了します。指紋はフロントマターではなくページの本文を対象にし、改行コードを正規化します — そのため整形やフロントマターの微修正で誤って「stale」になることはありません。典型的な流れ: 英語ページを編集 → ovellum check が日本語のミラーを指摘 → 変更を翻訳 → ovellum check --update-translations で再スタンプ。

このページを編集