🌍

Astro × microCMSでスワヒリ語対応のブログサイトを作る

2023/08/04に公開

AstroとmicroCMSを使用してブログサイトを実装しました。
サイト全体のスワヒリ語対応にも挑戦しています。
https://hatuseseri.com/

はじめに

友達が結婚をしました。本当におめでたい。
僕がWeb制作の勉強を始めた頃、彼女はアフリカに旅に出ていました。
彼女の行動がとても魅力的で、全くスキルがないのに「サイトを作らせてほしい!」とお願いして作らせてもらいました。
僕にとって初めてゼロから作ったサイトでした。
そんな思い出深いサイトを、結婚を祝してリニューアルすることにしました。

リニューアル前のサイト 出来栄えはあまり良くない

技術概要

  • Astro v2.8.1
  • MicroCMS

Astroのインテグレーション

その他

  • GSAP

開発フロー

環境構築、記事取得などについてはこの記事ではスルーします。
Astroのインストール
Astroのディレクトリ構造
AstroとmicroCMSでつくるブログサイト

多言語化(Astro)

Astroでは多言語化に対するビルドインでのサポートが現時点ではないので、astro-i18nextというインテグレーションで対応しました。
基本的な使用方法としては、astro-i18nextの設定ファイルに対応する言語をリスト化しておき、generateコマンドでpagesディレクトリ内のastroファイルを言語別に生成する流れなっています。

astro-i18next.config.mjs
/** @type {import('astro-i18next').AstroI18nextConfig} */
export default {
  defaultLocale: "ja",
  locales: ["ja", "sw"],
};
// generate前
src
└── pages
    ├── about.astro
    └── index.astro
npx astro-i18next generate
// generate後
src
└── pages
    ├── sw
    |   ├── about.astro
    |   └── index.astro
    ├── about.astro
    └── index.astro

言語別に表示内容を変更する際はpublicディレクトリにlocalesディレクトリを作成し、言語別にディレクトリを分けてjsonデータを作成します。

 public
  └── locales  # create this folder to store your translation strings
      ├── ja
      |   └── translation.json
      └── sw
          └── translation.json

それぞれのjsonで、表示する文言を管理します。

// public/locales/ja/translation.json
{
  "home": {
    "title": "タイトル",
    "description": "こんにちは。良い天気ですね"
  },
}
// public/locales/sw/translation.json
{
  "home": {
    "title": "kichwa",
    "description": "Habari. Ni hali ya hewa nzuri"
  },
}

tファンクションで表示できます。

〇〇.astro
---
import { t } from "i18next";
---
~~~~
    <h1>{t("home.title")}</h1>
    <p>{t("home.description")}</p>
~~~~

他にも、対応言語のバリエーションを検索エンジンに知らせるためのhreflang属性を一覧で表示することや、表示中の言語コードを取得する機能、表示中の言語に合わせてリンクのパスを変化させる機能などがあります。

about.astro
// 表示中の言語コードを取得する...i18next.language
// 言語に合わせてパスを変える...localizePath
// hreflang属性の作成...HeadHrefLangs
---
import i18next from "i18next";
import { localizePath } from "astro-i18next";
import { HeadHrefLangs } from "astro-i18next/components";
---

<html lang={i18next.language}>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>...</title>
    <meta name="description" content="..." />
    <HeadHrefLangs />
  </head>
  <body>
      ...
          <a href={localizePath("/hoge")}>...</a>
      ...
  </body>
</html>
about.html
<html lang="sw">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>...</title>
    <meta name="description" content="..." />
    <link rel="alternate" hreflang="ja" href="https://.../about/" />
    <link rel="alternate" hreflang="sw" href="https://.../about/sw" />
  </head>
  <body>
      ...
	  <a href="/hoge/sw">...</a>       
      ...
  </body>
</html>

多言語化(microCMS)

前章でAstro側の多言語化対応を行ったので、コンテンツ管理側でも多言語化対応を行います。

microCMSの公式ブログによると、対応方法は2つあり、APIを分けて管理する方法と、一つのAPIで言語ごとにスキーマを作成する方法があるようです。今回は2言語だったので、後者を採用しましたが言語が増えた場合は考え直す必要がありそうです。
スキーマを作成する際はフィールドIDを言語コードにしています。

記事管理画面

カテゴリー管理画面

APIプレビューでレスポンスを確認します。

{
    "contents": [
        {
            "id": "...",
            "createdAt": "...",
            "updatedAt": "...",
            "publishedAt": "...",
            "revisedAt": "...",
            "title": {
                "fieldId": "title_group",
                "ja": "タイトル_日本語",
                "sw": "タイトル_スワヒリ語"
            },
            "content": {
                "fieldId": "content_group",
                "ja": "コンテンツ_日本語",
                "sw": "コンテンツ_スワヒリ語"},
            "eyecatch": {...},
            "category": {
                "id": "...",
                "createdAt": "...",
                "updatedAt": "...",
                "publishedAt": "...",
                "revisedAt": "...",
                "ja": "カテゴリー名_日本語",
                "sw": "カテゴリー名_スワヒリ語"
            }
        }
    ],
    "totalCount": 1,
    "offset": 0,
    "limit": 10
}

CMS側で作成したデータをAstro側で表示します。
スキーマのフィールドIDを言語コードにしているのでastro-i18nextのtファンクションでデータを参照すると、表示中の言語に合わせて参照するデータを変えることができます。

[blogId].astro(記事詳細)
---
import i18next from "i18next";
import { getBlogDetail } from "@library/microcms";

// 詳細記事ページの全パスを取得
export async function getStaticPaths() {
    const response = await getBlogs({ limit: 100, fields: ["id"] });
    return response.contents.map((content: any) => ({
        params: {
            blogId: content.id,
        },
    }));
}
//記事の詳細情報を取得
const { blogId } = Astro.params;
const blog = await getBlogDetail(blogId as string);
---
<div set:html={blog.content[i18next.language]}></div>

まとめ

Astroを使ってサイトを作り上げたのは今回が初めてだったので、良い経験となった。スタイリングの最適解が自分の中で見つかっていないので、他の人がどうしているのか気になった。
ページネーションの実装をすっかり忘れてしまっていたので、どこかのタイミングで改修します。

参考

Astroを自動CLIでインストール
ディレクトリ構成
AstroとmicroCMSでつくるブログサイト
astro-i18next
microCMSで多言語サイトに対応する方法

Discussion