Astro&Markdown/Markdocで作ったサイトで、簡単な言語切り替え機能を実装する
個人のポートフォリオサイトを、2023年からAstroで構築しています。 サイトの要件として、「日本語でも英語でも表示すること」があったため、勉強も兼ねてある程度自前で実装してみました。 基本方針 英語をベースとする 日 […]
目次
個人のポートフォリオサイトを、2023年からAstroで構築しています。
サイトの要件として、「日本語でも英語でも表示すること」があったため、勉強も兼ねてある程度自前で実装してみました。
基本方針
- 英語をベースとする
- 日本語の場合、
hidetaka.dev/ja-JP/
をベースURLにする - Markdown / Makdocファイルは、言語ごとに用意する
- サードパーティの多言語対応ライブラリは、あえて使わない
言語別に用意したMarkdown/Markdocファイルを、言語別に読み込む
今回は配置するファイルもあまり多くないため、次のようなシンプルなディレクトリ構成とします。
src/contents/blog/hello.mdoc
src/contents/blog/hello-ja.mdoc
Astroのsrc/component/Hello.astro
ファイルを作成しましょう。
Astro.props.lang
で言語を受け取る形とし、getEntryBySlug
のファイルパスを変化させます。
---
import { getEntryBySlug } from 'astro:content';
const { lang = 'en' } = Astro.props;
const entry = await getEntryBySlug('blog', `hello${/ja/.test(lang) ? '-ja' : ''}`);
---
{Content ? (
<Content />
): null}
URLのパスから言語を判定する
今回のサイトでは、次のようにURLで言語を判定します。
example.com/
: Englishexample.com/ja-JP
: Japanese
pathname
から取得するため、ヘルパー関数を用意しましょう。
export function getLanguageFromURL(pathname: string) {
// ja,en,es
//const langCodeMatch = pathname.match(/\/([a-z]{2}-?[a-z]{0,2})/);
// ja-JP, en-US
const langCodeMatch = pathname.match(/^\/(\w{2})-([\w-]{2,})/);
return langCodeMatch ? langCodeMatch[1] : 'en-US';
}
あとはsrc/pages
以下のファイルで、言語を取得する様に実装します。
const currentPage = new URL(Astro.request.url).pathname;
const lang = getLanguageFromURL(currentPage);
言語ごとのページファイルを作成する
動的に設定できるのが理想だとは思いますが、2言語だけなので物理で押し通します。
src/pages
以下に言語ごとにファイルを作成し、併せてsrc/containers
やsrc/components
にページ用のファイルも用意しましょう。
src/pages/index.astro
src/pages/ja-JP/index.astro
src/containers/pages/IndexPage.astro
ページで表示するコンテンツ自体は全てページ用ファイルに任せ、src/pages
のファイルは言語の取得とコンポーネントの呼び出しのみを行います。
---
import { getLanguageFromURL } from "../../libs/urlUtils/lang.util"
import IndexPage from "../../containers/pages/IndexPage.astro";
const currentPage = new URL(Astro.request.url).pathname;
const lang = getLanguageFromURL(currentPage);
---
<IndexPage lang={lang} />
言語切り替え機能を実装する
最後に言語切り替え方法です。
こちらもAstro.request.url
から取得したpathname
を元に、URLを書き換える関数を作ります。
export const changeLanguageURL = (pathname: string, targetLang: 'en-US' | 'ja-JP' = 'en-US'): string => {
const lang = getLanguageFromURL(pathname)
if (lang === targetLang) return pathname
if (lang === 'en-US') {
return `/${targetLang}${pathname}`
}
const replaceTarget = targetLang === 'en-US' ? '' : `/${targetLang}`
return pathname.replace(/^\/(\w{2})-([\w-]{2,})/, replaceTarget)
}
あとはリンクタグにこの関数の実行結果を渡しましょう。
---
import { changeLanguageURL } from "../../../libs/urlUtils/lang.util";
const { pathname } = new URL(Astro.request.url)
---
<nav>
<ul>
<a href={changeLanguageURL(pathname, 'ja-JP')}>Japanese</a>
<a href={changeLanguageURL(pathname, 'en-US')}>English</NavIatem>
</ul>
</nav>