デモページ
フッターから言語を選択すれば、URLやtitleが変更されることがわかると思います。
なかなか上手いこといくライブラリが無かったので自分で実装してみました。今回は日本語と英語のみの実装となります。
[lang]
┬ page.tsx
└ demo - page.tsx
分かりにくいかと思いますが、全てのページは [lang]
以下に配置され、lang
のパラメータによってテキストが変更されるというイメージです。言語ファイルは Language.tsx
にまとめて書きます。
トップページからは各言語のトップページへの遷移のみを行います。つまり言語が ja
ならば、トップページは /ja/
になります。
1'use client';
2import { useRouter } from 'next/navigation';
3import { useEffect } from 'react';
4
5export default function Home() {
6 const router = useRouter();
7 useEffect(() => {
8 const language: string =
9 window.navigator.language || window.navigator.language[0];
10 if (language.includes('ja')) {
11 router.push('/ja/');
12 } else {
13 router.push('/en/');
14 }
15 }, [router]);
16 return <></>;
17}
18
言語ごとに文章をまとめたファイルです。これはページごとに管理してもいいかもしれません。
1const langType = ['ja', 'en'];
2
3type LangType = (typeof langType)[number];
4
5type Meta = {
6 title: string;
7 description: string;
8};
9type I18nText = {
10 home: Meta & {
11 head: string;
12 body: string;
13 demo: string;
14 };
15 demo: Meta & {
16 head: string;
17 body: string;
18 home: string;
19 };
20 footer: {
21 footer: string;
22 };
23};
24
25const i18nText: Record<LangType, I18nText> = {
26 ja: {
27 home: {
28 title: 'サイトタイトル',
29 description: 'サイト説明文。',
30 head: 'トップページ',
31 body: 'ここはトップページです。',
32 demo: 'デモページ',
33 },
34 demo: {
35 title: 'ページ',
36 description: 'ページ説明文。',
37 head: 'デモページ',
38 body: 'ここはデモページです。',
39 home: 'ホームページ',
40 },
41 footer: {
42 footer: 'フッター',
43 },
44 },
45 en: {
46 home: {
47 title: 'Site Title',
48 description: 'Site description.',
49 head: 'Home Page',
50 body: 'Here is Home Page',
51 demo: 'Demo Page',
52 },
53 demo: {
54 title: 'Page',
55 description: 'Page description.',
56 head: 'Demo Page',
57 body: 'Here is Demo Page',
58 home: 'Home Page',
59 },
60 footer: {
61 footer: 'footer',
62 },
63 },
64};
65
66export { i18nText, langType };
67export type { LangType };
68
メタタグは layout.tsx
で書きます。
1import { ReactNode } from 'react';
2import type { Metadata } from 'next';
3import { i18nText, LangType } from '@/components/Language';
4
5type Params = {
6 lang: LangType;
7};
8
9export async function generateMetadata({
10 params,
11}: {
12 params: Promise<Params>;
13}): Promise<Metadata> {
14 const { lang } = await params;
15 const t = i18nText[lang];
16
17 const title = t.home.title;
18 const description = t.home.description;
19
20 return {
21 title,
22 description,
23 };
24}
25
26export const dynamicParams = false;
27
28export function generateStaticParams() {
29 return [{ lang: 'ja' }, { lang: 'en' }];
30}
31
32export default function Layout({ children }: { children: ReactNode }) {
33 return <>{children}</>;
34}
35
lang
は useParams()
により取得します。
1'use client';
2import { useParams } from 'next/navigation';
3import { i18nText, LangType } from '@/components/Language';
4import Container from '@/components/Container';
5import Link from 'next/link';
6
7export default function Page() {
8 const params = useParams<{ lang: LangType }>();
9 const { lang } = params;
10 const t = i18nText[lang];
11
12 return (
13 <Container lang={lang}>
14 <div className='bg-white p-2'>
15 <h1 className='text-center text-2xl'>{t.home.head}</h1>
16 <p>{t.home.body}</p>
17 <Link href={`/${lang}/demo/`} className='text-sky-600'>
18 {t.home.demo}
19 </Link>
20 </div>
21 </Container>
22 );
23}
24
小規模のサイトや web アプリでは使えるのではないでしょうか。