diff --git a/astro.config.mjs b/astro.config.mjs
index fd294ce..d72fd9c 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -2,11 +2,22 @@
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
+const languages = ['en', 'ja'];
+
// https://astro.build/config
export default defineConfig({
site: 'https://docs.vivliostyle.org',
output: 'static',
- integrations: [sitemap()],
+ integrations: [sitemap({
+ filter: (page) => {
+ const url = new URL(page);
+ return languages.includes(url.pathname.split('/')[1]);
+ },
+ i18n: {
+ defaultLocale: 'en',
+ locales: Object.fromEntries(languages.map((lang) => [lang, lang])),
+ },
+ })],
build: {
format: 'directory',
},
diff --git a/src/layouts/DocsLayout.astro b/src/layouts/DocsLayout.astro
index 4c2ccf5..b4fec7e 100644
--- a/src/layouts/DocsLayout.astro
+++ b/src/layouts/DocsLayout.astro
@@ -12,9 +12,10 @@ interface Props {
description?: string;
lang?: string;
showBreadcrumb?: boolean;
+ availableLanguages?: ('en' | 'ja')[];
}
-const { title, description = '', lang = 'en', showBreadcrumb = true } = Astro.props;
+const { title, description = '', lang = 'en', showBreadcrumb = true, availableLanguages = [] } = Astro.props;
const currentPath = Astro.url.pathname;
---
@@ -25,6 +26,15 @@ const currentPath = Astro.url.pathname;
{title} | Vivliostyle Documentation
+
+ {availableLanguages.map((language) => (
+
+ ))}
+
diff --git a/src/layouts/LanguageSwitchLayout.astro b/src/layouts/LanguageSwitchLayout.astro
new file mode 100644
index 0000000..db7f53c
--- /dev/null
+++ b/src/layouts/LanguageSwitchLayout.astro
@@ -0,0 +1,58 @@
+---
+/**
+ * 言語切り替えレイアウト - 言語検出とリダイレクト
+ *
+ * Accept-Languageヘッダーを確認し、適切な言語ページにリダイレクト。
+ * SSRが必要な場合はクライアントサイドで処理。
+ */
+
+interface Props {
+ targetPath: string;
+ availableLanguages?: ('en' | 'ja')[];
+ defaultLanguage?: 'en' | 'ja';
+}
+
+const {
+ targetPath,
+ availableLanguages = ['en', 'ja'],
+ defaultLanguage = 'en',
+} = Astro.props;
+---
+
+
+
+
+
+ Vivliostyle Documentation
+
+
+
+
+
+
+
+
+ Welcome to the documentation. Please navigate to English documentation.
+
+
diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro
new file mode 100644
index 0000000..78d9481
--- /dev/null
+++ b/src/pages/[...slug].astro
@@ -0,0 +1,69 @@
+---
+import LanguageSwitchLayout from '../layouts/LanguageSwitchLayout.astro';
+
+export async function getStaticPaths() {
+ const languages = ['en', 'ja'] as const;
+ const pageComponents = Object.entries(
+ import.meta.glob<{
+ getStaticPaths?: () => Promise<
+ { params: { slug: string | undefined } }[]
+ >;
+ }>('./**/*.astro', { eager: true })
+ ).flatMap((it) => {
+ const [key, value] = it;
+ const { getStaticPaths } = value;
+ const matched = /^\.\/(\w+)\/(.+\/)[^/]+\.astro$/.exec(key);
+ if (!getStaticPaths || !matched) {
+ return [];
+ }
+ const [, language, path] = matched;
+ if (!languages.includes(language as (typeof languages)[number])) {
+ return [];
+ }
+ return [
+ {
+ getStaticPaths,
+ language: language as (typeof languages)[number],
+ path,
+ } as const,
+ ];
+ });
+
+ const pages = (
+ await Promise.all(
+ pageComponents.map(async ({ getStaticPaths, ...rest }) => ({
+ ...rest,
+ staticPaths: await getStaticPaths(),
+ }))
+ )
+ ).flatMap(({ staticPaths, path, language }) =>
+ staticPaths.map(({ params }) => ({
+ language,
+ slug: `${path}${params.slug ?? ''}`,
+ }))
+ );
+ const allSlugs = new Set(pages.map(({ slug }) => slug));
+ return Array.from(allSlugs).map((slug) => {
+ const availableLanguages = pages.flatMap((page) =>
+ page.slug === slug ? [page.language] : []
+ );
+ return {
+ params: { slug },
+ props: {
+ availableLanguages,
+ defaultLanguage: availableLanguages.includes('en')
+ ? 'en'
+ : availableLanguages[0],
+ },
+ };
+ });
+}
+
+const { availableLanguages, defaultLanguage } = Astro.props;
+---
+
+
diff --git a/src/pages/en/cli/[...slug].astro b/src/pages/en/cli/[...slug].astro
index 67f3446..97b8d85 100644
--- a/src/pages/en/cli/[...slug].astro
+++ b/src/pages/en/cli/[...slug].astro
@@ -88,7 +88,12 @@ const prevPage = currentIndex > 0 ? sortedDocs[currentIndex - 1] : null;
const nextPage = currentIndex < sortedDocs.length - 1 ? sortedDocs[currentIndex + 1] : null;
---
-
+
diff --git a/src/pages/en/index.astro b/src/pages/en/index.astro
index 8322f8f..7daf517 100644
--- a/src/pages/en/index.astro
+++ b/src/pages/en/index.astro
@@ -36,7 +36,12 @@ const title = indexDoc?.data?.title || 'Welcome to Vivliostyle Documentation';
const description = indexDoc?.data?.description || 'Official documentation for Vivliostyle';
---
-
+