このページとあなたの好きなAIアシスタントを使ってドキュメントを要約します
バージョン履歴
- "Solid の useIntlayer API の使用法を直接プロパティアクセスに更新"v8.9.02026/5/4
- "initコマンドを追加"v7.5.92025/12/30
- "`alternates` オブジェクトに `x-default` の記述を追加"v7.0.62025/11/1
- "履歴の初期化"v7.0.02025/6/29
このページのコンテンツはAIを使用して翻訳されました。
英語の元のコンテンツの最新バージョンを見るこのドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンクドキュメントのMarkdownをクリップボードにコピー
Intlayerを使ってNext.js 16のウェブサイトを翻訳する | 国際化(i18n)
GitHubのアプリケーションテンプレートをご覧ください。
目次
Intlayerとは?
Intlayerは、最新のウェブアプリケーションにおける多言語対応を簡素化するために設計された革新的なオープンソースの国際化(i18n)ライブラリです。Intlayerは、強力なApp Routerを含む最新のNext.js 16フレームワークとシームレスに統合されます。効率的なレンダリングのためにサーバーコンポーネントでの動作に最適化されており、Turbopackとも完全に互換性があります。
Intlayerを使うことで、以下が可能になります:
- コンポーネントレベルで宣言的な辞書を使用して翻訳を簡単に管理。
- メタデータ、ルート、コンテンツを動的にローカライズ。
- クライアントサイドおよびサーバーサイドの両方のコンポーネントで翻訳にアクセス。
- 自動生成された型によるTypeScriptサポートを保証し、オートコンプリートやエラー検出を向上。
- 動的なロケール検出や切り替えなどの高度な機能を活用。
IntlayerはNext.js 12、13、14、16と互換性があります。Next.jsのPage Routerを使用している場合は、このガイドを参照してください。 ロケールルーティングはSEO、バンドルサイズ、パフォーマンスに役立ちます。不要な場合は、このガイドを参照してください。 Next.js 12、13、14のApp Routerを使用している場合は、このガイドを参照してください。
Next.jsアプリケーションでIntlayerをセットアップするステップバイステップガイド
ステップ1:依存関係のインストール
npmを使って必要なパッケージをインストールします:
コードをクリップボードにコピー
npm install intlayer next-intlayernpx intlayer initintlayer
next-intlayer
IntlayerをNext.jsと統合するパッケージです。Next.jsの国際化のためのコンテキストプロバイダーやフックを提供します。さらに、IntlayerをWebpackやTurbopackと統合するためのNext.jsプラグイン、ユーザーの優先ロケール検出、クッキー管理、URLリダイレクト処理のためのプロキシも含まれています。
ステップ2: プロジェクトの設定
最終的な構成は以下のようになります:
コードをクリップボードにコピー
.├── src│ ├── app│ │ ├── [locale]│ │ │ ├── layout.tsx # Intlayerプロバイダー用のロケールレイアウト│ │ │ ├── page.content.ts│ │ │ └── page.tsx│ │ └── layout.tsx # スタイルとグローバルプロバイダー用のルートレイアウト│ ├── components│ │ ├── client-component-example.content.ts│ │ ├── ClientComponentExample.tsx│ │ ├── LocaleSwitcher│ │ │ ├── localeSwitcher.content.ts│ │ │ └── LocaleSwitcher.tsx│ │ ├── server-component-example.content.ts│ │ └── ServerComponentExample.tsx│ └── proxy.ts├── intlayer.config.ts├── next.config.ts├── package.json└── tsconfig.jsonロケールルーティングが不要な場合、intlayerはシンプルなプロバイダー/フックとして使用できます。詳細はこのガイドを参照してください。
アプリケーションの言語を設定するための設定ファイルを作成します:
コードをクリップボードにコピー
import { Locales, type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
internationalization: {
locales: [
Locales.ENGLISH,
Locales.FRENCH,
Locales.SPANISH,
// 他のロケール
],
defaultLocale: Locales.ENGLISH,
},
};
export default config;この設定ファイルを通じて、ローカライズされたURLの設定、プロキシリダイレクト、クッキー名、コンテンツ宣言の場所と拡張子の指定、コンソールでのIntlayerログの無効化などが行えます。利用可能なパラメータの完全なリストについては、設定ドキュメントを参照してください。
ステップ3: Next.jsの設定にIntlayerを統合する
Next.jsのセットアップをIntlayerを使うように設定します:
コードをクリップボードにコピー
import type { NextConfig } from "next";
import { withIntlayer } from "next-intlayer/server";
const nextConfig: NextConfig = {
/* ここに設定オプションを記述 */
};
export default withIntlayer(nextConfig);withIntlayer() は Next.js プラグインで、Intlayer を Next.js と統合するために使用されます。これにより、コンテンツ宣言ファイルのビルドが保証され、開発モードでそれらを監視します。また、Webpack や Turbopack 環境内で Intlayer の環境変数を定義します。さらに、パフォーマンス最適化のためのエイリアスを提供し、サーバーコンポーネントとの互換性を確保します。
withIntlayer()関数は Promise 関数です。ビルド開始前に Intlayer の辞書を準備することができます。他のプラグインと一緒に使用したい場合は、await で待機できます。例:tsコードをコピーコードをクリップボードにコピー
const nextConfig = await withIntlayer(nextConfig);const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);export default nextConfigWithOtherPlugins;同期的に使用したい場合は、
withIntlayerSync()関数を使用できます。例:tsコードをコピーコードをクリップボードにコピー
const nextConfig = withIntlayerSync(nextConfig);const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);export default nextConfigWithOtherPlugins;
Intlayer は、コマンドラインフラグ
--webpack、--turbo、または--turbopack、および現在の Next.js バージョン に基づいて、プロジェクトが webpack または Turbopack を使用しているかどうかを自動的に検出します。
next>=16以降、Rspack を使用している場合は、Turbopack を無効にして webpack 設定を使用するように Intlayer に明示的に強制する必要があります。tsコードをコピーコードをクリップボードにコピー
withRspack(withIntlayer(nextConfig, { enableTurbopack: false }));
ステップ4: 動的ロケールルートの定義
RootLayout の内容をすべて削除し、以下のコードに置き換えます:
コードをクリップボードにコピー
import type { PropsWithChildren, FC } from "react";
import "./globals.css";
const RootLayout: FC<PropsWithChildren> = ({ children }) => (
// `next-themes`、`react-query`、`framer-motion` などの他のプロバイダーで子要素をラップすることも可能です。
<>{children}</>
);
export default RootLayout;RootLayoutコンポーネントを空のままにしておくことで、<html>タグにlangおよびdir属性を設定できます。
動的ルーティングを実装するには、[locale]ディレクトリに新しいレイアウトを追加してロケールのパスを指定します:
コードをクリップボードにコピー
import { type NextLayoutIntlayer, IntlayerClientProvider } from "next-intlayer";
import { Inter } from "next/font/google";
import { getHTMLTextDir } from "intlayer";
const inter = Inter({ subsets: ["latin"] });
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
const { locale } = await params;
return (
<html lang={locale} dir={getHTMLTextDir(locale)}>
<body className={inter.className}>
<IntlayerClientProvider locale={locale}>
{children}
</IntlayerClientProvider>
</body>
</html>
);
};
export default LocaleLayout;[locale]パスセグメントはロケールを定義するために使用されます。例:/en-US/aboutはen-USを指し、/fr/aboutはfrを指します。
この段階で、Error: Missing <html> and <body> tags in the root layout.というエラーが発生します。これは予期されたもので、/app/page.tsxファイルはもはや使用されておらず、削除して問題ありません。代わりに、[locale]パスセグメントが/app/[locale]/page.tsxページを有効にします。その結果、ブラウザでは/en、/fr、/esのようなパスでページにアクセスできるようになります。デフォルトのロケールをルートページとして設定するには、ステップ7のproxy設定を参照してください。
次に、アプリケーションのレイアウト内で generateStaticParams 関数を実装します。
コードをクリップボードにコピー
export { generateStaticParams } from "next-intlayer"; // 挿入する行
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
/*... 残りのコード */
};
export default LocaleLayout;generateStaticParams は、アプリケーションがすべてのロケールに対して必要なページを事前にビルドすることを保証し、実行時の計算を減らしユーザー体験を向上させます。詳細は Next.js の generateStaticParams に関するドキュメント を参照してください。
Intlayer は export const dynamic = 'force-static'; と連携して、すべてのロケールのページが事前にビルドされることを保証します。
ステップ5: コンテンツの宣言
翻訳を格納するためのコンテンツ宣言を作成・管理します:
コードをクリップボードにコピー
import { t, type Dictionary } from "intlayer";
const pageContent = {
key: "page",
content: {
getStarted: {
main: t({
en: "Get started by editing",
fr: "Commencez par éditer",
es: "Comience por editar",
}),
pageLink: "src/app/page.tsx",
},
},
} satisfies Dictionary;
export default pageContent;コンテンツ宣言は、contentDirディレクトリ(デフォルトは./src)に含まれている限り、アプリケーションのどこにでも定義できます。また、コンテンツ宣言ファイルの拡張子は(デフォルトで.content.{json,ts,tsx,js,jsx,mjs,cjs})に一致する必要があります。
詳細については、コンテンツ宣言のドキュメントを参照してください。
ステップ6: コード内でコンテンツを利用する
アプリケーション全体でコンテンツ辞書にアクセスします:
コードをクリップボードにコピー
import type { FC } from "react";
import { ClientComponentExample } from "@components/ClientComponentExample";
import { ServerComponentExample } from "@components/ServerComponentExample";
import { type NextPageIntlayer } from "next-intlayer";
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
const PageContent: FC = () => {
const content = useIntlayer("page");
return (
<>
<p>{content.getStarted.main}</p>
<code>{content.getStarted.pageLink}</code>
</>
);
};
const Page: NextPageIntlayer = async ({ params }) => {
const { locale } = await params;
return (
<IntlayerServerProvider locale={locale}>
<PageContent />
<ServerComponentExample />
<ClientComponentExample />
</IntlayerServerProvider>
);
};
export default Page;IntlayerClientProviderはクライアントサイドのコンポーネントにロケールを提供するために使用されます。レイアウトを含む任意の親コンポーネントに配置できます。ただし、Next.jsはページ間でレイアウトコードを共有するため、レイアウトに配置することが推奨されます。レイアウトでIntlayerClientProviderを使用することで、各ページごとに再初期化する必要がなくなり、パフォーマンスが向上し、アプリケーション全体で一貫したローカリゼーションコンテキストを維持できます。IntlayerServerProviderはサーバー側の子コンポーネントにロケールを提供するために使用されます。レイアウトには設定できません。レイアウトとページは共通のサーバーコンテキストを共有できません。なぜなら、サーバーコンテキストシステムはリクエストごとのデータストア(Reactのcache メカニズム)に基づいており、アプリケーションの異なるセグメントごとに「コンテキスト」が再作成されるためです。プロバイダーを共有レイアウトに配置すると、この分離が破られ、サーバーコンポーネントに正しくサーバーコンテキストの値が伝播されなくなります。
コードをクリップボードにコピー
"use client";
import type { FC } from "react";
import { useIntlayer } from "next-intlayer";
export const ClientComponentExample: FC = () => {
const content = useIntlayer("client-component-example"); // 関連するコンテンツ宣言を作成
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};コードをクリップボードにコピー
import type { FC } from "react";
import { useIntlayer } from "next-intlayer/server";
export const ServerComponentExample: FC = () => {
const content = useIntlayer("server-component-example"); // 関連するコンテンツ宣言を作成
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};コンテンツをalt、title、href、aria-labelなどのstring属性で使用したい場合は、関数の値を使用できます。例えば:
htmlコードをコピーコードをクリップボードにコピー
<img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />
useIntlayer フックの詳細については、ドキュメントを参照してください。
アプリケーションが既に存在する場合は、Intlayer コンパイラ と 抽出コマンド を組み合わせて、1 秒で何千ものコンポーネントを変換できます。
(任意)ステップ7: ロケール検出のためのプロキシ設定
ユーザーの優先ロケールを検出するためのプロキシを設定します:
コードをクリップボードにコピー
export { intlayerProxy as proxy } from "next-intlayer/proxy";
export const config = {
matcher:
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
};intlayerProxy はユーザーの優先ロケールを検出し、設定で指定された適切なURLにリダイレクトするために使用されます。さらに、ユーザーの優先ロケールをクッキーに保存することも可能にします。
複数のプロキシを連結する必要がある場合(例えば、認証付きのintlayerProxyやカスタムプロキシと組み合わせる場合)、Intlayer はmultipleProxiesというヘルパーを提供しています。
コードをクリップボードにコピー
import { multipleProxies, intlayerProxy } from "next-intlayer/proxy";import { customProxy } from "@utils/customProxy";export const proxy = multipleProxies([intlayerProxy, customProxy]);(任意)ステップ8: メタデータの国際化
ページのタイトルなどのメタデータを国際化したい場合は、Next.jsが提供する generateMetadata 関数を使用できます。その中で、getIntlayer 関数からコンテンツを取得してメタデータを翻訳できます。
コードをクリップボードにコピー
import { type Dictionary, t } from "intlayer";
import { Metadata } from "next";
const metadataContent = {
key: "page-metadata",
content: {
title: t({
en: "Create Next App",
fr: "Créer une application Next.js",
es: "Crear una aplicación Next.js",
}),
description: t({
en: "Generated by create next app",
fr: "Généré par create next app",
es: "Generado por create next app",
}),
},
} satisfies Dictionary<Metadata>;
export default metadataContent;コードをクリップボードにコピー
import { getIntlayer, getMultilingualUrls } from "intlayer";
import type { Metadata } from "next";
import type { LocalPromiseParams } from "next-intlayer";
export const generateMetadata = async ({
params,
}: LocalPromiseParams): Promise<Metadata> => {
const { locale } = await params;
const metadata = getIntlayer("page-metadata", locale);
/**
* 各ロケールのすべてのURLを含むオブジェクトを生成します。
*
* 例:
* ```ts
* getMultilingualUrls('/about');
*
* // 戻り値
* // {
* // en: '/about',
* // fr: '/fr/about',
* // es: '/es/about',
* // }
* ```
*/
const multilingualUrls = getMultilingualUrls("/");
const localizedUrl =
multilingualUrls[locale as keyof typeof multilingualUrls];
return {
...metadata,
alternates: {
canonical: localizedUrl,
languages: { ...multilingualUrls, "x-default": "/" },
},
openGraph: {
url: localizedUrl,
},
};
};
// ... 残りのコードnext-intlayerからインポートされたgetIntlayer関数は、コンテンツをIntlayerNodeでラップして返し、ビジュアルエディタとの統合を可能にします。対照的に、intlayerからインポートされたgetIntlayer関数は、追加のプロパティなしで直接コンテンツを返します。
代わりに、getTranslation 関数を使用してメタデータを宣言することもできます。ただし、メタデータの翻訳を自動化し、コンテンツを外部化するためには、コンテンツ宣言ファイルを使用することが推奨されます。
コードをクリップボードにコピー
import {
type IConfigLocales,
getTranslation,
getMultilingualUrls,
} from "intlayer";
import type { Metadata } from "next";
import type { LocalPromiseParams } from "next-intlayer";
export const generateMetadata = async ({
params,
}: LocalPromiseParams): Promise<Metadata> => {
const { locale } = await params;
const t = <T>(content: IConfigLocales<T>) => getTranslation(content, locale);
return {
title: t<string>({
en: "My title",
fr: "Mon titre",
es: "Mi título",
}),
description: t({
en: "My description",
fr: "Ma description",
es: "Mi descripción",
}),
};
};
// ... 残りのコードメタデータの最適化について詳しくは、公式Next.jsドキュメントをご覧ください。
(オプション)ステップ9: sitemap.xml と robots.txt の多言語対応
sitemap.xml と robots.txt を多言語対応にするには、Intlayer が提供する getMultilingualUrls 関数を使用できます。この関数を使うことで、サイトマップ用の多言語 URL を生成できます。
コードをクリップボードにコピー
import { getMultilingualUrls } from "intlayer";
import type { MetadataRoute } from "next";
const sitemap = (): MetadataRoute.Sitemap => [
{
url: "https://example.com",
alternates: {
languages: {
...getMultilingualUrls("https://example.com"),
"x-default": "https://example.com",
},
},
},
{
url: "https://example.com/login",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/login"),
"x-default": "https://example.com/login",
},
},
},
{
url: "https://example.com/register",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/register"),
"x-default": "https://example.com/register",
},
},
},
];
export default sitemap;コードをクリップボードにコピー
import type { MetadataRoute } from "next";
import { getMultilingualUrls } from "intlayer";
const getAllMultilingualUrls = (urls: string[]) =>
urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
const robots = (): MetadataRoute.Robots => ({
rules: {
userAgent: "*",
allow: ["/"],
disallow: getAllMultilingualUrls(["/login", "/register"]),
},
host: "https://example.com",
sitemap: `https://example.com/sitemap.xml`,
});
export default robots;サイトマップの最適化については、公式の Next.js ドキュメントをご覧ください。robots.txt の最適化については、公式の Next.js ドキュメントをご覧ください。
(オプション)ステップ10: コンテンツの言語を変更する
Next.js でコンテンツの言語を変更するには、推奨される方法として Link コンポーネントを使用してユーザーを適切なローカライズされたページにリダイレクトする方法があります。 Link コンポーネントはページのプリフェッチを可能にし、完全なページリロードを回避するのに役立ちます。
コードをクリップボードにコピー
"use client";
import type { FC } from "react";
import {
Locales,
getHTMLTextDir,
getLocaleName,
getLocalizedUrl,
} from "intlayer";
import { useLocale } from "next-intlayer";
import Link from "next/link";
export const LocaleSwitcher: FC = () => {
const { locale, pathWithoutLocale, availableLocales, setLocale } =
useLocale();
return (
<div>
<button popoverTarget="localePopover">{getLocaleName(locale)}</button>
<div id="localePopover" popover="auto">
{availableLocales.map((localeItem) => (
<Link
href={getLocalizedUrl(pathWithoutLocale, localeItem)}
key={localeItem}
aria-current={locale === localeItem ? "page" : undefined}
onClick={() => setLocale(localeItem)}
replace // 「戻る」ブラウザボタンが前のページにリダイレクトすることを保証します
>
<span>
{/* ロケール - 例: FR */}
{localeItem}
</span>
<span>
{/* 自身のロケールでの言語名 - 例: Français */}
{getLocaleName(localeItem, locale)}
</span>
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
{/* 現在のロケールでの言語名 - 例: Francés(現在のロケールが Locales.SPANISH の場合) */}
{getLocaleName(localeItem)}
</span>
<span dir="ltr" lang={Locales.ENGLISH}>
{/* 英語での言語名 - 例: French */}
{getLocaleName(localeItem, Locales.ENGLISH)}
</span>
</Link>
))}
</div>
</div>
);
};代替方法として、useLocaleフックで提供されるsetLocale関数を使用することもできます。この関数はページのプリフェッチを許可しません。詳細はuseLocaleフックのドキュメント を参照してください。
また、 onLocaleChange オプションに関数を設定して、ロケールが変更されたときにカスタム関数をトリガーすることも可能です。
コードをクリップボードにコピー
"use client";import { useRouter } from "next/navigation";import { useLocale } from "next-intlayer";import { getLocalizedUrl } from "intlayer";// ... 残りのコードconst router = useRouter();const { setLocale } = useLocale({ onLocaleChange: (locale) => { router.push(getLocalizedUrl(pathWithoutLocale, locale)); },});return ( <button onClick={() => setLocale(Locales.FRENCH)}>フランス語に変更</button>);ドキュメント参照:
(オプション) ステップ 1 : コンポーネントのコンテンツを抽出する
既存のコードベースがある場合、数千のファイルを変換するのは時間がかかることがあります。
このプロセスを容易にするために、Intlayerは、コンポーネントを変換しコンテンツを抽出するための コンパイラ / エクストラクタ を提案しています。
セットアップするには、intlayer.config.ts ファイルに compiler セクションを追加します。
コードをクリップボードにコピー
import { type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
// ... 他の構成
compiler: {
/**
* コンパイラを有効にするかどうかを指定します。
*/
enabled: true,
/**
* 出力ファイルのパスを定義します。
*/
output: ({ fileName, extension }) => `./${fileName}${extension}`,
/**
* 変換後にコンポーネントを保存するかどうかを指定します。これにより、コンパイラを一度だけ実行してアプリを変換し、その後削除することができます。
*/
saveComponents: false,
/**
* 辞書キーの接頭辞
*/
dictionaryKeyPrefix: "",
},
};
export default config;コンポーネントを変換してコンテンツを抽出するためにエクストラクタを実行します
コードをクリップボードにコピー
npx intlayer extract(オプション)ステップ11:ローカライズされたリンクコンポーネントの作成
アプリケーションのナビゲーションが現在のロケールを尊重するようにするために、カスタムの Link コンポーネントを作成できます。このコンポーネントは内部のURLに自動的に現在の言語をプレフィックスとして付加します。例えば、フランス語ユーザーが「About」ページへのリンクをクリックすると、 /about ではなく /fr/about にリダイレクトされます。
この動作は以下の理由で有用です:
- SEOとユーザー体験:ローカライズされたURLは検索エンジンが言語別のページを正しくインデックスし、ユーザーに好みの言語でコンテンツを提供するのに役立ちます。
- 一貫性:アプリケーション全体でローカライズされたリンクを使用することで、ナビゲーションが現在のロケール内に留まり、予期しない言語切り替えを防ぎます。
- 保守性:URLの管理を単一のコンポーネントに集約することで、コードベースの保守や拡張が容易になります。
以下は、TypeScript によるローカライズされた Link コンポーネントの実装です:
コードをクリップボードにコピー
"use client";
import { getLocalizedUrl } from "intlayer";
import NextLink, { type LinkProps as NextLinkProps } from "next/link";
import { useLocale } from "next-intlayer";
import type { PropsWithChildren, FC } from "react";
/**
* 指定された URL が外部かどうかを確認するユーティリティ関数。
* URL が http:// または https:// で始まる場合、外部とみなされます。
*/
export const checkIsExternalLink = (href?: string): boolean =>
/^https?:\/\//.test(href ?? "");
/**
* 現在のロケールに基づいて href 属性を適応させるカスタム Link コンポーネント。
* 内部リンクの場合、`getLocalizedUrl` を使用して URL にロケールを付加します (例: /fr/about)。
* これにより、ナビゲーションが同じロケールコンテキスト内に留まることが保証されます。
*/
export const Link: FC<PropsWithChildren<NextLinkProps>> = ({
href,
children,
...props
}) => {
const { locale } = useLocale();
const isExternalLink = checkIsExternalLink(href.toString());
// リンクが内部であり、有効な href が提供されている場合、ローカライズされた URL を取得します。
const hrefI18n: NextLinkProps["href"] =
href && !isExternalLink ? getLocalizedUrl(href.toString(), locale) : href;
return (
<NextLink href={hrefI18n} {...props}>
{children}
</NextLink>
);
};仕組み
外部リンクの検出:
ユーティリティ関数checkIsExternalLinkは、URL が外部かどうかを判断します。外部リンクはローカライズの必要がないため、そのまま保持されます。現在のロケールの取得:
useLocaleフックは、現在のロケール(例: フランス語ならfr)を提供します。URL のローカライズ:
内部リンク(外部以外)の場合、getLocalizedUrlを使用して、自動的に現在のロケールを URL の先頭に付加します。つまり、ユーザーがフランス語の設定であれば、/aboutを渡すと/fr/aboutに変換されます。リンクの返却:
コンポーネントはローカライズされた URL を持つ<a>要素を返し、ナビゲーションがロケールと一致するようにします。
この Link コンポーネントをアプリケーション全体に統合することで、一貫性のある言語対応のユーザー体験を維持しつつ、SEO やユーザビリティの向上というメリットも得られます。