主網站與子網站的設置
===
###### With Next.js App Router + next-intl
:::info
:radio_button: [回到目錄攻略](https://hackmd.io/@hJJ8etrATgudRfKA1gryew/BJiplPwMC)
:::
0.先看成果
---

隨著點選各個子項目(北部、中部、南部、東部),其網址也會跟著變動,連結到各自的子網站頁面!~~所謂的有關係又沒關係~~:grin:
1.建立子網站的資料夾
---
建立目錄如下截圖:

除了原有的主網站`main`之外,額外再建立`east`、`middle`、`north`、`south`資料夾,每個資料夾底下再各自建立`layout.tsx`與`page.tsx`。
> 資料夾底下page.tsx的作用?
這就是`Next.js` `App router`在使用者建立路由時,超方便的一大機制 -- 只要新建資料夾,並在其底下`page.tsx`作為主要呈現畫面的檔案,醬子就能幫你自動生成網址路徑啦!
2.page資料初步寫入
---
> @locale/east/page.tsx
> @locale/middle/page.tsx
> @locale/north/page.tsx
> @locale/south/page.tsx
```typescript=
// ${AREA}為變數,可再自行做調整
import { getTranslations, unstable_setRequestLocale } from "next-intl/server";
type Props = {
params: { locale: string };
};
const ${AREA}Page = async ({ params: { locale } }: Props) => {
unstable_setRequestLocale(locale);
const t = await getTranslations();
return (
<div>
<h2>{t("${AREA}")}</h2>
</div>
);
};
export default ${AREA}Page;
```
3.components初步建立
---
每個子網站都會各自有共用的`header`或`footer`,常用到的元件就要包進`components`裡面了呀!初步先建置`Header.tsx`:
> @locale/east/components/Header.tsx
> @locale/middle/components/Header.tsx
> @locale/north/components/Header.tsx
> @locale/south/components/Header.tsx
```typescript=
// ${AREA}、${CITY}為變數,可再自行做調整
import { Link } from "@lib/navigation";
import { getTranslations } from "next-intl/server";
export default async function ${AREA}Header() {
const t = await getTranslations();
return (
<header>
<p>{t("${AREA}-header")}</p>
<nav>
<ul>
<li>
<Link href="/main">{t("home")}</Link>
</li>
<li>
<Link href="/${AREA}/${CITY}">{t("${CITY}")}</Link>
</li>
...
</ul>
</nav>
<hr />
</header>
);
}
```
4.新創網址寫入config.ts
---
還記得[在地化路徑配置](https://hackmd.io/XBHzsZN5REq9P81CcWCTyg#4%E5%88%9D%E8%A8%AD%E5%9C%A8%E5%9C%B0%E5%8C%96%E8%AA%9E%E8%A8%80%E8%B7%AF%E5%BE%91%E9%85%8D%E7%BD%AE)這段文嗎?
在每個子網站中,又延伸出許多地點/縣市的網頁,雖然在建立資料夾與`page.tsx`的同時,已自動升成可到達的網址,但多國語言套件不知道呀!所以就必須把設置好的網址一一寫入congig.ts--
> @src/lib/config.ts
```typescript=
import { Pathnames } from "next-intl/navigation";
export const locales = ["en", "zh"] as const;
export const pathnames = {
"/main": "/main", //接續往下加入新的網址
"/north": "/north",
"/middle": "/middle",
"/south": "/south",
"/east": "/east",
"/east/yilan": "/east/yilan",
"/middle/miaoli": "/middle/miaoli",
"/north/newpei": "/north/newpei",
"/south/chiayi": "/south/chiayi",
} satisfies Pathnames<typeof locales>;
export const localePrefix = "always";
export type AppPathnames = keyof typeof pathnames;
```
5.layout初步寫入
---
要讓各子網站的`header`重複出現,當然少不了透過`layout`來排兵部陣!
> @locale/east/layout.tsx
> @locale/middle/layout.tsx
> @locale/north/layout.tsx
> @locale/south/layout.tsx
```typescript=
import ${AREA}Header from "@/src/app/[locale]/${AREA}/components/Header";
import { locales } from "@lib/config";
import { NextIntlClientProvider, useMessages } from "next-intl";
import { unstable_setRequestLocale } from "next-intl/server";
import React from "react";
export function generateStaticParams() {
return locales.map((locale) => ({ locale }));
}
type Props = { children: React.ReactNode; params: { locale: string } };
export default function ${AREA}Layout({ children, params: { locale } }: Props) {
const messages = useMessages();
unstable_setRequestLocale(locale);
return (
<>
<NextIntlClientProvider messages={messages}>
<${AREA}Header /> // 重複的header底家
<main>{children}</main>
</NextIntlClientProvider>
</>
);
}
```