Skip to content
Cloud AI エンジニア入門ガイド
Go back

11. AstroPaperでUI文言の翻訳と多言語対応

この章の全体像として、文言の場所、選ばれる流れ、型で検出する、翻訳の外の4つを番号順に並べ、UIを日本語にして漏れも確認できるようになることを示した図

シリーズ目次 前章: 10. AstroPaperでOG画像の自動生成とSEO 次章: 12. AstroPaperのビルドとデプロイ

Table of contents

Open Table of contents

この章のねらい

AstroPaperのテンプレートには、Recent Posts、Search、Back to top といった英語のUI文言が入っています。日本語で運用するなら、当然ここを直したくなります。仕組みと変更手順、それから翻訳ファイルだけでは変わらない部分への対処を見ていきます。

文言はどこにあるのか

UI文言は src/i18n/ にまとまっています。

src/i18n/
├── index.ts        # ロケールに応じて文言を選ぶ
├── format.ts       # {{変数}} を差し替える
├── types.ts        # 文言の型定義
└── lang/
    └── en.ts       # 英語の文言

lang/en.ts の中身は、用途ごとにグループ分けされたオブジェクトです。

export default {
  nav: {
    home: "Home",
    posts: "Posts",
    tags: "Tags",
    about: "About",
    archives: "Archives",
    search: "Search",
  },
  post: {
    publishedAt: "Published at",
    updatedAt: "Updated",
    sharePostOn: "Share this post on {{platform}}",
    // ...
  },
  // ...
} satisfies UIStrings;src/i18n/lang/en.ts

グループは次のように分かれています。

グループ対象
navヘッダーのメニュー
post記事詳細ページの各種ラベル
paginationページ送り
homeトップページの見出し
footerフッター
pages一覧系ページのタイトルと説明
a11y読み上げソフト向けのラベル
notFound404ページ

グループ名と、画面のどこを受け持つかを対応させると次のようになります。

nav・post・pagination・home・footer・pages・a11y・notFoundの8グループが、それぞれ画面のどこの文言を受け持つかを並べた図

文言が選ばれる流れ

ロケールの決定から翻訳ファイルの参照、変数の差し替えまでの流れを示した図

選択を担当しているのは src/i18n/index.ts です。

const modules = import.meta.glob<{ default: UIStrings }>("./lang/*.ts", {
  eager: true,
});

const translations: Record<string, UIStrings> = {};
for (const [path, mod] of Object.entries(modules)) {
  const locale = path.slice("./lang/".length, -".ts".length);
  translations[locale] = mod.default;
}

export function useTranslations(locale: string = "en"): UIStrings {
  return translations[locale] ?? translations["en"];
}src/i18n/index.ts

やっていることは3つです。

  1. import.meta.globlang/ 内のファイルをすべて読み込む
  2. ファイル名がそのままロケール名になるja.tsja
  3. 該当する言語がなければ英語にフォールバックする

つまり、ファイルを1つ足すだけで新しい言語が登録される設計です。一覧に追記するような作業は不要です。

ここで引っかかります。フォールバックはファイル単位ですtranslations[locale] が見つからなければ丸ごと英語になりますが、ja.ts がある状態で個々のキーが欠けていても、そこだけ英語で補われることはありません。欠けたキーは実行時に undefined になり、画面には何も出ません。一部だけ翻訳しておく、という運用はできません。

各ページでは、次のように呼び出されています。

const locale = Astro.currentLocale ?? config.site.lang;
const t = useTranslations(locale);

Astro.currentLocale はAstroが判定した現在のロケールです。取得できない場面では、設定の site.lang が使われます。

変数の差し替え

一部の文言には {{platform}} のような差し込み位置があります。

sharePostOn: "Share this post on {{platform}}",src/i18n/lang/en.ts

これを実際の値に置き換えるのが tplStr です。

export function tplStr(
  template: string,
  vars: Record<string, string | number>
): string {
  return template.replace(/\{\{(\w+)\}\}/g, (_, key: string) => {
    const value = vars[key];
    return value !== undefined && value !== null ? String(value) : "";
  });
}src/i18n/format.ts

言語によって語順が変わっても困らないよう、埋め込み位置を文中の好きなところに置けるようになっています。

日本語にする手順

1. 翻訳ファイルを作る

src/i18n/lang/en.ts をコピーして src/i18n/lang/ja.ts を作り、値を日本語に書き換えます。

import type { UIStrings } from "../types";

export default {
  nav: {
    home: "ホーム",
    posts: "記事一覧",
    tags: "タグ",
    about: "このサイトについて",
    archives: "アーカイブ",
    search: "検索",
  },
  post: {
    publishedAt: "公開日",
    updatedAt: "更新日",
    sharePostIntro: "この記事を共有する:",
    sharePostOn: "{{platform}}でこの記事を共有する",
    sharePostViaEmail: "メールでこの記事を共有する",
    tagLabel: "タグ",
    backToTop: "ページ先頭へ戻る",
    goBack: "戻る",
    editPage: "このページを編集",
    previousPost: "前の記事",
    nextPost: "次の記事",
  },
  // 以下、すべてのグループを同様に翻訳する
} satisfies UIStrings;src/i18n/lang/ja.ts

2. 型チェックに頼る

末尾の satisfies UIStrings を落とさないでください。これは「このオブジェクトは UIStrings の形を満たしている」と宣言する記法で、項目を書き忘れるとエラーになります

pnpm astro check

これで翻訳漏れがその場で出ます。手作業で見比べる必要はありません。

3. 設定の言語を合わせる

site: {
  lang: "ja",
},astro-paper.config.ts

これで <html lang="ja"> になり、useTranslations にも "ja" が渡ります。

4. Astroのi18n設定を確認する

astro.config.ts には、Astro本体のi18n設定があります。

i18n: {
  locales: ["ja"],
  defaultLocale: "ja",
  routing: {
    prefixDefaultLocale: false,
  },
},astro.config.ts

false なら、URLは /posts/ のままです。単一言語のサイトはこれでいいので、触らないでください。

true にすると、getRelativeLocaleUrl が生成するリンクが /ja/posts/ のような接頭辞付きになります。ただし設定を変えるだけでは動きません。Astroのルーティングはファイルベースなので、src/pages/posts/ などを src/pages/ja/posts/ へ移して、実際にそのURLのページを生成させる必要があります。移さずに true にすると、リンク先にページがなくて404です。

locales に書いた言語コードと src/i18n/lang/ のファイル名は、必ず対応させてください。

ここまでの4つを順に済ませれば、UI文言は日本語になります。

翻訳ファイルの作成、型チェックによる漏れの確認、site.langの変更、astro.config.tsのi18n設定という4段階を上から順に並べた図

翻訳ファイルで変わらないもの

ja.ts を作っただけでは変わらない部分があります。

日付の表示形式

日付は src/components/Datetime.astro が組み立てています。

const date = datetime.format("D MMM, YYYY");src/components/Datetime.astro

2 Aug, 2026 のような英語式の表記になります。日本語式にしたければ、この書式を書き換えます。

const date = datetime.format("YYYY年M月D日");

dayjs の書式記号で指定します。月名を日本語で出したい場合は、dayjs の日本語ロケールを読み込む必要があります。

なお、アーカイブページの月名は Intl.DateTimeFormat を使っており、site.lang に応じて自動で切り替わります。こちらは設定だけで日本語になります。

トップページの文章

src/pages/index.astro の冒頭にある紹介文は、コードに直接書かれています。翻訳ファイルではどうにもならないので、ファイルを開いて自分の言葉に置き換えてください。

<h1 class="my-4 inline-block text-4xl font-bold sm:my-8 sm:text-5xl">
  Mingalaba
</h1>src/pages/index.astro

見出しの文言もここにあります。

固定ページと記事

src/content/pages/about.md と各記事は、当然ながら自分で書くものです。翻訳の仕組みとは関係ありません。

この3か所は、それぞれ別のファイルを直接編集する必要があります。

日付の表示形式、トップページの紹介文、固定ページと記事の3か所について、そのままだとどうなるかと直す場所を並べた図

複数言語で運用する場合

同じサイトを複数言語で公開したい場合は、次の作業が追加で必要になります。

  1. astro.config.tslocales に言語を追加する
  2. src/i18n/lang/ に言語ごとのファイルを置く
  3. 記事そのものを言語ごとに用意し、URLで切り分ける
  4. 言語を切り替えるUIを自分で追加する

READMEの表現は i18n ready、つまり多言語対応の準備ができている、です。多言語サイト機能が完成しているとは書いていません。UI文言の切り替え基盤だけが用意されていて、その上の記事の多言語運用は自分で組み立てる。そういう線引きです。

どこまでが用意されていて、どこからが自分の仕事なのかを分けておきます。

テーマが用意しているUI文言の切り替え基盤と、記事の多言語運用として自分で組み立てる作業を左右に並べて比べた図

URLの組み立てには、テーマ内でも使われている getRelativeLocaleUrl が使えます。Astroが提供する関数で、設定に応じた言語接頭辞を自動で付けてくれます。

import { getRelativeLocaleUrl } from "astro:i18n";

const url = getRelativeLocaleUrl(locale, "posts");

また、src/utils/withBase.ts には接頭辞を取り除く補助関数も用意されています。

export function stripLocale(pathname: string, locale: string): string {
  const prefix = `/${locale}`;
  if (pathname === prefix) return "/";
  if (pathname.startsWith(`${prefix}/`)) return pathname.slice(prefix.length);
  return pathname;
}src/utils/withBase.ts

作業チェックリスト

日本語化を一通り終えるための確認項目です。

作業対象
UI文言の翻訳src/i18n/lang/ja.ts
言語設定astro-paper.config.tssite.lang
ロケール宣言astro.config.tsi18n
日付の書式src/components/Datetime.astro
トップページの紹介文src/pages/index.astro
「このサイトについて」src/content/pages/about.md
タイムゾーンastro-paper.config.tssite.timezone
翻訳漏れの確認pnpm astro check

要点

参考資料


シリーズ目次 前章: 10. AstroPaperでOG画像の自動生成とSEO 次章: 12. AstroPaperのビルドとデプロイ


Share this post:

Previous Post
12. AstroPaperのビルドとデプロイ
Next Post
10. AstroPaperでOG画像の自動生成とSEO