このページとあなたの好きなAIアシスタントを使ってドキュメントを要約します
バージョン履歴
- "Initial history"v9.1.32025/8/6
このページのコンテンツはAIを使用して翻訳されました。
英語の元のコンテンツの最新バージョンを見るIf you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Intlayer を使用して SolidStart Web サイトを翻訳する | 国際化 (i18n)
目次
このガイドでは、サーバーレンダリングされた SolidStart アプリケーションを扱います。ロケール検出はリクエスト時に行われ、ページは正しい言語でサーバー上にレンダリングされ、検索エンジンが必要とする <html lang>、hreflang、サイトマップのシグナルはサーバー側で出力されます。
代替手段ではなく Intlayer を選ぶ理由
@solid-primitives/i18n や i18next などの主要なソリューションと比較して、Intlayer は次のような統合された最適化を備えたソリューションです。
Intlayer は、コンポーネントレベルのコンテンツスコープ、リアクティブな翻訳、および国際化 (i18n) の拡張に必要なすべての機能を提供することで、Solid と完全に連携するように最適化されています。
大量の JSON ファイルをページにロードするのではなく、必要なコンテンツのみをロードします。Intlayer は、バンドルとページのサイズを最大 50% 削減するのに役立ちます。
アプリケーションのコンテンツのスコープを設定すると、大規模なアプリケーションのメンテナンスが容易になります。コンテンツコードベース全体を確認するという精神的な負担を負うことなく、単一の機能フォルダを複製または削除できます。さらに、Intlayer は完全に型指定されており、コンテンツの正確性を保証します。
AI プロバイダーのコストで、選択した LLM を使用して CI/CD パイプラインで翻訳を自動化します。Intlayer は、コンテンツ抽出を自動化するコンパイラや、バックグラウンドでの翻訳を支援する Web プラットフォーム も提供します。
大量の JSON ファイルをコンポーネントに接続すると、パフォーマンスと反応性の問題が発生する可能性があります。Intlayer は、ビルド時のコンテンツ読み込みを最適化します。
SolidStart アプリケーションで Intlayer をセットアップするためのステップバイステップガイド
依存関係のインストール
npm を使用して必要なパッケージをインストールします:
bashコードをコピーコードをクリップボードにコピー
npx intlayer init --interactive--interactiveフラグはオプションです。AI エージェントの場合はintlayer-cli initを使用してください。このコマンドは環境を検出し、必要なパッケージをインストールします。例:
bashコードをコピーコードをクリップボードにコピー
npm install intlayer solid-intlayer vite-intlayerintlayer
solid-intlayer
Intlayer を Solid アプリケーションに統合するパッケージです。Solid の国際化のためのコンテキストプロバイダーとフックを提供します。
vite-intlayer
Intlayer を Vite バンドラー に統合するための Vite プラグインと、ユーザーの優先ロケールを検出し、Cookie を管理し、URL リダイレクトを処理するロケールルーティングハンドラーが含まれています。
vite-intlayerは、単なるビルド時の懸念事項ではなく、サーバー側の懸念事項でもあります。SolidStart の Nitro サーバーが実行するリクエストハンドラーを提供します。dependenciesに維持するのが安全なデフォルトです。コンパイルされた.outputディレクトリをデプロイし、Nitro がハンドラーをインライン化する場合にのみ、devDependenciesに移動できます。プロジェクトの設定
アプリケーションの言語を設定するための設定ファイルを作成します:
intlayer.config.tsコードをコピーコードをクリップボードにコピー
import { type IntlayerConfig, Locales } from "intlayer"; const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // その他のロケール ], defaultLocale: Locales.ENGLISH, }, routing: { mode: "prefix-no-default", }, }; export default config;prefix-no-defaultを使用すると、デフォルトのロケールはプレフィックスのない URL から提供されます:plaintextコードをコピーコードをクリップボードにコピー
/ /about → 英語 (デフォルトロケール)/fr /fr/about → フランス語/es /es/about → スペイン語この設定ファイルを使用して、ローカライズされた URL、ミドルウェアのリダイレクト、Cookie 名、コンテンツ宣言の場所と拡張子の設定、コンソールでの Intlayer ログの無効化などを行うことができます。利用可能なパラメータの完全なリストについては、設定ドキュメントを参照してください。
Vite 設定への Intlayer の統合
Intlayer プラグインを設定に追加します:
vite.config.tsコードをコピーコードをクリップボードにコピー
import { solidStart } from "@solidjs/start/config"; import { nitro } from "nitro/vite"; import { defineConfig } from "vite"; import { intlayer } from "vite-intlayer"; export default defineConfig({ plugins: [solidStart(), nitro(), intlayer()], });intlayer()Vite プラグインは、コンテンツ宣言ファイルをビルドし、開発モードで監視し、アプリケーション内に Intlayer 環境変数を定義します。また、パフォーマンスを最適化するエイリアスも提供します。ロケールルーティングはプラグインに付属しています
SolidStart は Nitro 上で動作し、
intlayer()はロケールルーティングハンドラーを Nitro のサーバーパイプラインに直接登録します(デフォルトでtrueになっているrouting.enableProxyオプションを介して)。他に接続するものは何もありません。構築されたサーバー上では、すべてのリクエストがルーターに到達する前に検査されます。- ロケールは URL プレフィックス、次に
INTLAYER_LOCALECookie、次にAccept-Languageヘッダーから読み取られます。 - 解決されたロケールがデフォルトのものではない場合、プレフィックスのない URL は対応するローカライズされた URL にリダイレクトされます (
/→/fr)。 - 冗長なプレフィックスを持つ URL は、正規の形式にリダイレクトされます (
/en/about→/about)。 - ロケール Cookie はレスポンスに書き戻されます。
- ロケールは URL プレフィックス、次に
コンテンツの宣言
翻訳を保存するためのコンテンツ宣言を作成および管理します:
src/contents/home.content.tsコードをコピーコードをクリップボードにコピー
import { type Dictionary, t } from "intlayer"; const homeContent = { key: "home-page", content: { title: t({ en: "Hello world!", fr: "Bonjour le monde !", es: "¡Hola mundo!", }), metaTitle: "SolidStart + Intlayer", metaDescription: t({ en: "A SolidStart application internationalized with Intlayer.", fr: "Une application SolidStart internationalisée avec Intlayer.", es: "Una aplicación SolidStart internacionalizada con Intlayer.", }), documentation: t({ en: "Visit start.solidjs.com to learn how to build SolidStart apps.", fr: "Visitez start.solidjs.com pour apprendre à créer des applications SolidStart.", es: "Visita start.solidjs.com para aprender a crear aplicaciones SolidStart.", }), }, } satisfies Dictionary; export default homeContent;⚠️ SolidStart 固有の注意点:
src/routes配下のすべての.ts/.tsxファイルはルートになり、.content.tsファイルにはデフォルトのエクスポートがあるため、ページとして検出されてしまいます。ページのコンテンツ宣言はルートディレクトリの外に配置してください (src/contents/が適しています)。コンポーネントのコンテンツは、src/componentsがファイルシステムルーターによってスキャンされないため、同じ場所に配置したままで問題ありません。コンテンツ宣言は、
contentDirディレクトリ(デフォルトでは./src)に含まれ、コンテンツ宣言ファイルの拡張子(デフォルトでは.content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml})と一致していれば、アプリケーション内のどこにでも定義できます。詳細については、コンテンツ宣言のドキュメントを参照してください。
ローカライズされたルーティングの追加
このステップの目標は、各言語に独自の URL を与えることです。これは検索エンジンがインデックスを作成する対象となります。
ページをオプションの動的セグメントに移動します。SolidStart のファイルシステムルーターでは、
[[locale]]は:locale?パスパターンにコンパイルされます:plaintextコードをコピーコードをクリップボードにコピー
src/routes/ [[locale]].tsx ← セグメントを検証するレイアウト [[locale]]/ index.tsx → / および /fr および /es about.tsx → /about および /fr/about および /es/about [...404].tsx → その他のすべてをキャッチレイアウトファイルの唯一の役割は、セグメントを設定されたロケールに制約することです:
src/routes/[[locale]].tsxコードをコピーコードをクリップボードにコピー
import type { RouteSectionProps } from "@solidjs/router";import { locales } from "intlayer";export const route = { matchFilters: { locale: locales, },};export default function LocaleLayout(props: RouteSectionProps) { return <>{props.children}</>;}@solidjs/routerは:locale?を 2 つのパターン(セグメントありとセグメントなし)に拡張し、降順の特定性でそれらを試行します。matchFiltersは、機能する設定と混乱を招く設定の差を生み出すものです:テーブルのすべての内容を表示テーブルをモーダルで開き、すべてのデータを明確に表示
URL matchFiltersなしmatchFiltersあり/fr/aboutフランス語の about ページ フランス語の about ページ /aboutAbout ページ (静的セグメントが優先) About ページ /unknownホーム ページ( locale=unknownで静かに表示)一致なし → キャッチオール 404 にフォールスルー 'prefix-all'ルーティングモードを使用する場合は[[locale]]の代わりに[locale](必須) を推奨し、'no-prefix'や'search-params'の場合はセグメントを完全に削除します。アプリケーションへのロケールの提供
URL はロケールの唯一の信頼できる情報源です。ミドルウェアはすでにリクエストをローカライズされたパスにリダイレクトしているため、ルートレイアウトでパスを読み取ることで、サーバーレンダリングとクライアントハイドレーションの一致が保たれ、クライアント側のナビゲーションごとに無料でロケールが更新されます。
src/app.tsxコードをコピーコードをクリップボードにコピー
import { MetaProvider } from "@solidjs/meta";import { Router, useLocation } from "@solidjs/router";import { FileRoutes } from "@solidjs/start/router";import { defaultLocale, getHTMLTextDir, getLocaleFromPath } from "intlayer";import { IntlayerProvider } from "solid-intlayer";import { createEffect, type ParentProps, Suspense } from "solid-js";import { isServer } from "solid-js/web";import { Nav } from "~/components/Nav";import "./app.css";const RootLayout = (props: ParentProps) => { const location = useLocation(); const locale = () => getLocaleFromPath(location.pathname) ?? defaultLocale; // サーバーは entry-server.tsx で <html> をレンダリングします。クライアント側のロケール間 // ナビゲーションでは、属性自体を更新する必要があります。 createEffect(() => { if (isServer) return; document.documentElement.lang = locale(); document.documentElement.dir = getHTMLTextDir(locale()); }); return ( <MetaProvider> <IntlayerProvider locale={locale()}> <Nav /> <Suspense>{props.children}</Suspense> </IntlayerProvider> </MetaProvider> );};export default function App() { return ( <Router root={RootLayout}> <FileRoutes /> </Router> );}IntlayerProviderはそのlocaleプロパティに反応するため、JSX 内でアクセサー呼び出しlocale()を渡すだけで十分です。Solid はそれをゲッターにコンパイルし、URL が変更されるとツリー全体が新しい言語で再レンダリングされます。サーバー上での HTML lang および dir 属性の設定
<html>エレメントはRouterの外部にあるentry-server.tsxによってレンダリングされます。代わりにリクエスト URL からロケールを読み取ります:src/entry-server.tsxコードをコピーコードをクリップボードにコピー
// @refresh reloadimport { createHandler, StartServer } from "@solidjs/start/server";import { defaultLocale, getHTMLTextDir, getLocaleFromPath } from "intlayer";import { getRequestEvent } from "solid-js/web";export default createHandler(() => ( <StartServer document={({ assets, children, scripts }) => { const url = getRequestEvent()?.request.url ?? "/"; const locale = getLocaleFromPath(url) ?? defaultLocale; return ( <html dir={getHTMLTextDir(locale)} lang={locale}> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> {assets} </head> <body> <div id="app">{children}</div> {scripts} </body> </html> ); }} />));クローラーは最初のバイトで正しい言語を受け取るようになります:
htmlコードをコピーコードをクリップボードにコピー
<html dir="ltr" lang="fr"></html>ページでの Intlayer の活用
アプリケーション全体でコンテンツ辞書にアクセスします:
src/routes/[[locale]]/index.tsxコードをコピーコードをクリップボードにコピー
import { Meta, Title } from "@solidjs/meta";import { useIntlayer } from "solid-intlayer";import Counter from "~/components/Counter";export default function Home() { const content = useIntlayer("home-page"); return ( <main> <Title>{content.metaTitle.value}</Title> <Meta content={content.metaDescription.value} name="description" /> <h1>{content.title}</h1> <Counter /> <p>{content.documentation}</p> </main> );}Solid では、
useIntlayerはリアクティブなコンテンツ(例:content)を返します。そのプロパティに直接アクセスできます。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フックの詳細については、ドキュメントを参照してください。コンテンツノードは単純な翻訳に限定されません。例えば、複数形化されたカウンター:
src/components/Counter.content.tsコードをコピーコードをクリップボードにコピー
import { type Dictionary, plural, t } from "intlayer";const counterContent = { key: "counter", content: { clicks: plural({ one: t({ en: "{{count}} click", fr: "{{count}} clic", es: "{{count}} clic", }), other: t({ en: "{{count}} clicks", fr: "{{count}} clics", es: "{{count}} clics", }), }), },} satisfies Dictionary;export default counterContent;src/components/Counter.tsxコードをコピーコードをクリップボードにコピー
import { useIntlayer } from "solid-intlayer";import { createSignal } from "solid-js";export default function Counter() { const [count, setCount] = createSignal(0); const content = useIntlayer("counter"); return ( <button onClick={() => setCount(count() + 1)} type="button"> {content.clicks(count())} </button> );}plural()はアクティブなロケールのIntl.PluralRulesを介してカテゴリを選択するため、3 つ以上の複数形を持つ言語でも余分なコードなしで動作します。ローカライズされた Link コンポーネントの作成
内部 URL に現在の言語のプレフィックスを自動的に付与するカスタム
Linkコンポーネントを作成します:src/components/LocalizedLink.tsxコードをコピーコードをクリップボードにコピー
import { A, type AnchorProps } from "@solidjs/router";import { getLocalizedUrl } from "intlayer";import { useLocale } from "solid-intlayer";import type { ParentComponent } from "solid-js";export const LocalizedLink: ParentComponent<AnchorProps> = (props) => { const { locale } = useLocale(); const isExternal = () => /^[a-z][a-z0-9+.-]*:/i.test(props.href); const localizedHref = () => isExternal() ? props.href : getLocalizedUrl(props.href, locale()); return <A {...props} href={localizedHref()} />;};src/components/Nav.tsxコードをコピーコードをクリップボードにコピー
import { useIntlayer } from "solid-intlayer";import type { Component } from "solid-js";import { LocaleSwitcher } from "./LocaleSwitcher";import { LocalizedLink } from "./LocalizedLink";export const Nav: Component = () => { const content = useIntlayer("nav"); return ( <nav> <LocalizedLink href="/">{content.home}</LocalizedLink> <LocalizedLink href="/about">{content.about}</LocalizedLink> <LocaleSwitcher /> </nav> );};一度
href="/about"と記述するだけで、アクティブなロケールに応じて/about、/fr/about、または/es/aboutが生成されるようになります。ページ内のどこでも手動でプレフィックスを付ける必要はありません。ロケールスイッチャーコンポーネントの作成
スイッチャーを
<select>ではなく実際のアンカーとしてレンダリングします。現在のページの各言語が新しいタブで開くことができるクロール可能なリンクになり、JavaScript のみのコントロールでは提供できない利点が得られます。getPathWithoutLocaleは現在のパスからロケールセグメントを取り除き、getLocalizedUrlはターゲットロケール用にそれを再構築するため、何もハードコーディングすることなくリンクがルーティングモードに従います。レンダリングされたロケールを変更するのはナビゲーションであり([[locale]]ルートは URL からそれを導出します)、setLocaleは選択をINTLAYER_LOCALECookie に保持するため、後でロケールなしの URL を訪問したときに同じ言語に解決されます。src/components/LocaleSwitcher.tsxコードをコピーコードをクリップボードにコピー
import { A, useLocation } from "@solidjs/router"; import { getHTMLTextDir, getLocaleName, getLocalizedUrl, getPathWithoutLocale, } from "intlayer"; import { useIntlayer, useLocale } from "solid-intlayer"; import { type Component, For } from "solid-js"; export const LocaleSwitcher: Component = () => { const content = useIntlayer("locale-switcher"); const location = useLocation(); const { locale, setLocale, availableLocales } = useLocale(); // 現在表示されているページの正規(ロケールなし)パス const pathWithoutLocale = () => getPathWithoutLocale(location.pathname); return ( <div> <button aria-label={content.label.value} popoverTarget="localePopover" type="button" > {getLocaleName(locale())} </button> <div id="localePopover" popover="auto"> <For each={availableLocales}> {(localeItem) => ( <A dir={getHTMLTextDir(localeItem)} // 完全一致のみ。デフォルトロケールのリンクがすべてのページでアクティブとして // フラグが立てられないようにするため end href={getLocalizedUrl(pathWithoutLocale(), localeItem)} hreflang={localeItem} lang={localeItem} onClick={() => setLocale(localeItem)} // ブラウザの「戻る」ボタンが前のページに戻ることを保証します replace > {/* 独自のロケールでの言語 - 例: Français */} {getLocaleName(localeItem)} </A> )} </For> </div> </div> ); };Solid では、
useLocaleからのlocaleはシグナルアクセサーです。リアクティブに現在の値を読み取るには、locale()(括弧付き)を使用します。getLocaleName(localeItem)は各言語を独自の言語で表示します(English / Français / Español)。2 番目の引数を渡すと、代わりに現在表示されている言語に名前を翻訳します:getLocaleName(localeItem, locale())は英語でEnglish / French / Spanish、日本語で英語 / フランス語 / スペイン語を返します。<A>は現在の URL に一致するリンクにすでにaria-current="page"を設定しているため、そこに追加するものはありません。replaceはレンダリングされた属性からルーターによって読み取られます。履歴エントリをプッシュするのではなく置き換えるため、ブラウザの「戻る」ボタンは前の言語の同じページではなく、切り替え前に訪問したページに戻ります。各リンクの
dirとhreflangは、右から左への言語名を正しく配置し、支援技術やクローラーに各リンクがどの言語を指しているかを伝えます。useLocaleフックの詳細については、ドキュメントを参照してください。canonical および hreflang リンクの出力
オプションhreflangアノテーションは、/about、/fr/about、/es/aboutが異なる言語での同じページであることを検索エンジンに伝えます。getMultilingualUrlsはルーティングモードに従って、正規(ロケールなし)のパスからそれらを導出するため、何もハードコーディングされません:src/components/AlternateLinks.tsxコードをコピーコードをクリップボードにコピー
import { defaultLocale, getMultilingualUrls, getPathWithoutLocale,} from "intlayer";import { type Component, For } from "solid-js";export type AlternateLinksProps = { /** レンダリングされているページの絶対 URL。 */ url: string;};export const AlternateLinks: Component<AlternateLinksProps> = (props) => { const multilingualUrls = () => { const { origin, pathname } = new URL(props.url); return Object.entries( getMultilingualUrls(`${origin}${getPathWithoutLocale(pathname)}`) ); }; const canonicalUrl = () => new URL(props.url).origin + new URL(props.url).pathname; return ( <> <link href={canonicalUrl()} rel="canonical" /> <For each={multilingualUrls()}> {([locale, localizedUrl]) => ( <link href={localizedUrl} hreflang={locale} rel="alternate" /> )} </For> <link href={ multilingualUrls().find(([locale]) => locale === defaultLocale)?.[1] } hreflang="x-default" rel="alternate" /> </> );};これをドキュメントの head(リクエスト URL が利用可能な場所)にレンダリングします:
src/entry-server.tsxコードをコピーコードをクリップボードにコピー
import { AlternateLinks } from "~/components/AlternateLinks";// … <head> 内、他の meta タグの隣:<AlternateLinks url={url} />;GET /fr/aboutは以下を出力します:htmlコードをコピーコードをクリップボードにコピー
<link href="https://example.com/fr/about" rel="canonical" /><link href="https://example.com/about" hreflang="en" rel="alternate" /><link href="https://example.com/fr/about" hreflang="fr" rel="alternate" /><link href="https://example.com/es/about" hreflang="es" rel="alternate" /><link href="https://example.com/about" hreflang="x-default" rel="alternate" />@solidjs/metaに関する注意: 執筆時点では、@solidjs/metaの<Title>と<Meta>はハイドレーション後にクライアントに適用されますが、SolidStart v2 のサーバーレンダリングされた<head>には出力されません。目が離せない修正がアップストリームで適用されるまでは、クローラーが JavaScript なしで表示する必要があるタグ(canonical、hreflang、必要に応じてtitle/description)を、上記のようにentry-server.tsxに直接レンダリングしてください。404 ページの管理
オプションsrc/routesのルートにあるスプラットルートは、ロケールセグメントに一致しなかったすべてのパスをキャッチします(matchFiltersによって拒否された無効なロケールプレフィックスを含む)。ロケールはルートレイアウトを通じて URL から取得されるため、404 ページは訪問者の言語で表示されます:src/routes/[...404].tsxコードをコピーコードをクリップボードにコピー
import { Title } from "@solidjs/meta";import { HttpStatusCode } from "@solidjs/start";import { useIntlayer } from "solid-intlayer";import { LocalizedLink } from "~/components/LocalizedLink";export default function NotFound() { const content = useIntlayer("not-found-page"); return ( <main> <Title>{content.metaTitle.value}</Title> <HttpStatusCode code={404} /> <h1>{content.title}</h1> <LocalizedLink href="/">{content.backHome}</LocalizedLink> </main> );}テーブルのすべての内容を表示テーブルをモーダルで開き、すべてのデータを明確に表示
リクエスト 結果 /xx404—xxは設定されたロケールではありません/nonexistentデフォルトロケールでの 404/fr/nonexistentフランス語での 404(Page introuvable)多言語サイトマップの生成
オプションIntlayer のサイトマップジェネレーターは、各パスをロケールごとに 1 つのエントリに拡張し、それらの間に
xhtml:linkの代替を接続するため、ルートは正規のロケールなしパスをリストするだけで済みます。フラットな URL のみを出力する基本的なジェネレーターとは異なり、Intlayer は各ページのローカライズされたバリアント間に双方向リンクを接続します。これにより、検索エンジンがローカライズされた URL を関連付け、適切なユーザーに適切な URL を提供するのに役立ちます。
SolidStart は、HTTP メソッドをエクスポートするファイルを API ルートに変換し、パスから
.ts拡張子を削除します。そのため、src/routes/sitemap.xml.tsは/sitemap.xmlで提供されます:src/routes/sitemap.xml.tsコードをコピーコードをクリップボードにコピー
import type { APIEvent } from "@solidjs/start/server"; import { generateSitemap } from "intlayer"; const SITE_URL = process.env.SITE_URL ?? "http://localhost:3000"; export const GET = (_event: APIEvent) => { const sitemap = generateSitemap( [ { path: "/", changefreq: "daily", priority: 1.0 }, { path: "/about", changefreq: "monthly", priority: 0.8 }, ], { siteUrl: SITE_URL } ); return new Response(sitemap, { headers: { "Content-Type": "application/xml" }, }); };output of GET /sitemap.xmlコードをコピーコードをクリップボードにコピー
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <url> <loc>https://example.com/about</loc> <changefreq>monthly</changefreq> <priority>0.8</priority> <xhtml:link rel="alternate" hreflang="en" href="https://example.com/about"/> <xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/about"/> <xhtml:link rel="alternate" hreflang="es" href="https://example.com/es/about"/> <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/about"/> </url></urlset>API ルートはオプションのパラメータをサポートしていないため、このファイルは
src/routesのルート、[[locale]]セグメントの外側に保持してください。サイトマップにはすでにすべてのロケールが含まれています。getMultilingualUrlsを使用して同じ方法でrobots.txtを構築し、Disallowエントリが機密パスのローカライズされた表記すべてをカバーするようにすることができます:src/routes/robots.txt.tsコードをコピーコードをクリップボードにコピー
import { getMultilingualUrls } from "intlayer"; const SITE_URL = process.env.SITE_URL ?? "http://localhost:3000"; const disallowedPaths = ["/admin", "/private"].flatMap((path) => Object.values(getMultilingualUrls(path)) ); export const GET = () => new Response( [ "User-agent: *", "Allow: /", ...disallowedPaths.map((path) => `Disallow: ${path}`), "", `Sitemap: ${SITE_URL}/sitemap.xml`, ].join("\n"), { headers: { "Content-Type": "text/plain" } } );サーバー関数でのロケールの取得
オプションサーバー関数または API ルートの内部から現在のロケールにアクセスしたい場合があります。
このようなプレフィックスベースの設定では、URL が決定権を持ちます:
getLocaleFromPathはリクエスト URL からプレフィックスを読み取ります。getLocaleはロケールプレフィックスを持たないリクエストのフォールバックです。INTLAYER_LOCALECookie を調べ、次にx-intlayer-localeヘッダーを調べ、Accept-Languageを交渉します。src/routes/[[locale]]/index.tsxコードをコピーコードをクリップボードにコピー
import { createAsync } from "@solidjs/router";import { getCookie, getIntlayer, getLocale, getLocaleFromPath } from "intlayer";import { getRequestEvent } from "solid-js/web";const loadLocalizedData = async () => { "use server"; const request = getRequestEvent()?.request; const locale = getLocaleFromPath(request?.url) ?? (await getLocale({ // リクエストから Cookie を取得(デフォルト: 'INTLAYER_LOCALE') getCookie: (name) => getCookie(name, request?.headers.get("cookie") ?? ""), // リクエストからヘッダーを取得(デフォルト: 'x-intlayer-locale')、 // Accept-Language の交渉にフォールバック getHeader: (name) => request?.headers.get(name) ?? undefined, })); // getIntlayer() を使用してコンポーネントの外部でコンテンツを取得 const content = getIntlayer("home-page", locale); return { locale, title: String(content.title) };};export default function Page() { const data = createAsync(() => loadLocalizedData()); return <p>{data()?.title}</p>;}ここで
getLocaleだけに頼らないでください。ロケール Cookie は訪問者が積極的に言語を切り替えたときにのみ書き込まれるため、/fr/...への初回訪問はデフォルトロケールに解決されてしまいます。コンポーネントのコンテンツの抽出
オプション既存のコードベースがある場合、何千ものファイルを変換するには時間がかかることがあります。
このプロセスを簡素化するために、Intlayer はコンポーネントを変換してコンテンツを抽出するための コンパイラ / エクストラクター を提案しています。
設定するには、
intlayer.config.tsファイルにcompilerセクションを追加します:intlayer.config.tsコードをコピーコードをクリップボードにコピー
import { type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { // ... 設定の残りの部分 compiler: { /** * コンパイラを有効にするかどうかを示します。 */ enabled: true, /** * 出力ファイルパスを定義します */ output: ({ fileName, extension }) => `./${fileName}${extension}`, /** * 変換後にコンポーネントを保存するかどうかを示します。 * * - `true` の場合、コンパイラはディスク上のコンポーネントファイルを書き換えます。これにより変換は永久的なものとなり、コンパイラは次のプロセスでの変換をスキップします。これにより、コンパイラはアプリを変換した後、削除できます。 * * - `false` の場合、コンパイラはビルド出力のコードにのみ `useIntlayer()` 関数呼び出しを注入し、ベースコードベースを元のまま維持します。変換はメモリ内でのみ行われます。 */ saveComponents: false, /** * 辞書キーのプレフィックス */ dictionaryKeyPrefix: "", }, }; export default config;エクストラクターを実行してコンポーネントを変換し、コンテンツを抽出します
bashコードをコピーコードをクリップボードにコピー
npx intlayer extractその後、ステップ 5 で説明した理由により、生成されたページのコンテンツファイルを
src/routesの外に移動してください。TypeScript の設定
Intlayer はモジュール拡張機能を使用して TypeScript のメリットを活かし、コードベースをより堅牢にします。
TypeScript の設定に自動生成された型が含まれていることを確認します:
tsconfig.jsonコードをコピーコードをクリップボードにコピー
{ compilerOptions: { // ... 既存の設定 }, include: [ "src", "*.ts", ".intlayer/**/*.ts", // 自動生成された型を含める ],}辞書キーとコンテンツパスがコンパイル時にチェックされるようになります:
tsxコードをコピーコードをクリップボードにコピー
useIntlayer("home-page"); // ✅useIntlayer("hom-page"); // ❌ Argument of type '"hom-page"' is not assignable to parameter of type 'keyof __DictionaryRegistry'
設定の検証
ビルドしてサーバーを起動し、以下のリクエストが期待通りに動作することを確認します:
コードをクリップボードにコピー
npm run buildnode .output/server/index.mjsテーブルをモーダルで開き、すべてのデータを明確に表示
| リクエスト | 期待されるレスポンス |
|---|---|
GET / | 200 — 英語 |
GET / (Accept-Language: fr 付き) | 302 → /fr |
GET / (INTLAYER_LOCALE=es Cookie 付き) | 302 → /es |
GET /fr | 200 — フランス語, <html lang="fr"> |
GET /fr/about | 200 — フランス語の about ページ |
GET /en/about | 302 → /about (正規リダイレクト) |
GET /xx | 404 |
GET /fr/nonexistent | 404 (フランス語) |
GET /sitemap.xml | 200 — 多言語 XML サイトマップ |
ページをレンダリングする行は vite dev 下でもまったく同じように動作します。3 つのリダイレクト行は、自分でハンドラーをミドルウェアとして登録しない限り、構築されたサーバーにのみ適用されます(ステップ 3 を参照)。
デブサーバーは Bun (bun --bun vite dev) ではなく Node (vite dev) で実行してください。SolidStart の SSR は現在、Bun ランタイム下でExpected a Response object, but received 'NodeResponse'で失敗します。これは Intlayer とは無関係で(プレーンなテンプレートでも再現します)、vite buildではなく開発サーバーにのみ影響します。
Git の設定
Intlayer によって生成されたファイルを無視することをお勧めします。これにより、それらを Git リポジトリにコミットすることを回避できます。
これを行うには、.gitignore ファイルに次の手順を追加します:
コードをクリップボードにコピー
# Intlayer によって生成されたファイルを無視.intlayerVS Code 拡張機能
Intlayer での開発体験を向上させるために、公式の Intlayer VS Code 拡張機能 をインストールできます。
この拡張機能は以下を提供します:
- 翻訳キーの 自動補完。
- 欠落している翻訳の リアルタイムエラー検出。
- 翻訳されたコンテンツの インラインプレビュー。
- 翻訳を簡単に作成および更新するための クイックアクション。
さらに進む
さらに進むには、ビジュアルエディタを実装するか、CMSを使用してコンテンツを外部化できます。