Skip to content

[Astro] 多言語対応(i18n)

Astro 製のサイトの多言語対応で行ったことをまとめました。

前提

  • Astro v5

config ファイルの設定

Astro には多言語対応のための i18n ルーティングが組み込まれています。 ルーティングの設定は astro.config.mjs ファイルで行います。

# astro.config.mjs

export default defineConfig({
  i18n: {
    defaultLocale: "ja",
    locales: ["ja", "en"],
    fallback: {
      en: "ja",
    },
  },
});

以下の内容になる設定の例です。

上記以外に https://en.chocolat5.com/ のようなサブドメインを使用したり、デフォルト言語もURLに含めたりなどの設定が可能です(詳細は公式ドキュメントを参照)

pages 内の構造

デフォルト言語は URL に含まない設定にしている場合のディレクトリ構造は次のようになります。

src/
  pages/
    index.astro
    about/
      index.astro
    en/
      index.astro
      about/
        index.astro

デフォルト言語と同じ構造で各言語のフォルダにファイルを作成します。 フォルダ名は locale と一致している必要があります。

html タグの言語設定

Astro が提供している API を使用して、現在の locale を取得します。

# Layout.astro

---
const currentLocale = Astro.currentLocale;
---

<html lang={currentLocale}>
  ...
</html>

ナビゲーションなどのリンクの設定

locale に対応した URL を取得できる Astro の API getRelativeLocaleUrl を使用してリンクを作成します。

getRelativeLocaleUrl には localepath の2つの引数を渡します。
path は省略可能で、略した場合はドメインのトップレベル / になります。

# Header.astro, Nav.astro など

---
import { getRelativeLocaleUrl } from "astro:i18n";
const currentLocale = Astro.currentLocale; // ja, en など
---

<header>
  <nav>
    <a href={getRelativeLocaleUrl(currentLocale, "about")}>About</a>
  </nav>
</header>

これにより locale = "ja" の場合は href="/about/" になり、
locale = "en" の場合は href="/en/about/" になります。

言語切り替えUI

言語切り替え用のUIの例です。
当サイトで実際に使用している言語切り替え用のUIです。2言語なのでシンプルな作りにしています。

---
const locales = ["ja", "en"];
const languages = {
  ja: "日本語",
  en: "English",
};

---

{
  locales.map((locale: string, index: number) => (
    <a class="support_button" href={getLocaleSwitcherURL(locale, pathname)}>
      {languages[locale]}
    </a>
  ))
}

getLocaleSwitcherURL() は正しいURLを取得するための自作の関数です。
日本語ボタンに対しては常に / で始まるURLを返し、Englishボタンに対しては常に /en で始まるURLを返します。

export const getLocaleSwitcherURL = (
  locale: string,
  pathname: string
): string => {
  if (locale === "ja") {
    return pathname.replace("/en", "");
  } else {
    return pathname.startsWith("/en") ? pathname : `/en${pathname}`;
  }
};

参照