多語系
介紹如何使用 @astrolicious/i18n 套件來支援多語系功能。
安裝套件
安裝 @astrolicious/i18n 套件:
bash
yarn add @astrolicious/i18n
然後在 astro.config.ts
中註冊 i18n
套件和設定語系,比如範例中設定網站可以支援繁體中文和英語兩種語系,且預設語系為繁體中文:
ts
import { defineConfig } from 'astro/config'
import i18n from '@astrolicious/i18n'
export default defineConfig({
integrations: [
i18n({
defaultLocale: 'zh-TW',
locales: ['zh-TW', 'en'],
}),
],
})
Layout 語系設定
在 Layout 檔案中設定語系相關基本設定:
astro
---
import I18nHead from '@astrolicious/i18n/components/I18nHead.astro'
import { getHtmlAttrs, getLocale } from 'i18n:astro'
import type { PageMeta } from '@stephenchenorg/astro/page'
import type { CompanySetting } from '@stephenchenorg/astro/company-setting'
// ...
const locale = getLocale()
const htmlLangMap: Record<string, string> = {
'zh-TW': 'zh-Hant-TW',
}
const htmlAttrs = getHtmlAttrs()
htmlAttrs.lang = htmlLangMap[locale] || locale
---
<!doctype html>
<html {...htmlAttrs}>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<I18nHead />
</head>
<body>
</body>
</html>
設定多語系路由
@astrolicious/i18n 套件中的路由資料夾是 src/routes
,只有在 src/routes
資料夾中的檔案才會套用語系前墜。如果有不想要套用的檔案,比如 API 相關的路由,可以放回 src/pages
資料夾。
在 src/routes
資料夾中設定多語系路由結構如下:
src/
└── routes/
├── about.astro
├── index.astro
└── posts/
├── [id].astro
└── index.astro
對應的路由設定:
zh-TW:
/
/posts/
/posts/1/
/about/
en:
/en/
/en/posts/
/en/posts/1/
/en/about/
設定翻譯檔
在 src/locales
目錄中新增翻譯檔:
src/locales/en/common.json
:
json
{
"hello": "Hello",
"world": "World",
"nav_about": "About",
"nav_home": "Home",
"nav_posts": "Posts"
}
src/locales/zh-TW/common.json
:
json
{
"hello": "你好",
"world": "世界",
"nav_about": "關於",
"nav_home": "首頁",
"nav_posts": "文章"
}
翻譯文字
使用 t
函數來翻譯文字:
astro
---
import { t, getLocalePath } from 'i18n:astro'
---
<div>
<h1>{t('hello')}</h1>
<p>{t('world')}</p>
</div>
語系連結
使用 getLocalePath
函數來生成語系連結:
astro
---
import { t, getLocalePath } from 'i18n:astro'
---
<a href={getLocalePath('/')}>{t('nav_home')}</a>
Layout 增加語系切換選項
在 Layout 中增加語系切換選項:
astro
---
import I18nHead from '@astrolicious/i18n/components/I18nHead.astro'
import { t, getHtmlAttrs, getLocale, getLocalePath, getSwitcherData } from 'i18n:astro'
import type { PageMeta } from '@stephenchenorg/astro/page'
import type { CompanySetting } from '@stephenchenorg/astro/company-setting'
// ...
const pathname = Astro.url.pathname
const switcherData = getSwitcherData()
const switcherLabels: Record<string, string> = {
en: 'English',
'zh-TW': '繁體中文',
}
---
<!doctype html>
<html {...htmlAttrs}>
<body>
<nav>
<ul>
<li class:list={[pathname === getLocalePath('/') && 'active']}>
<a href={getLocalePath('/')}>{t('nav_home')}</a>
</li>
<li class:list={[pathname.startsWith(getLocalePath('/posts')) && 'active']}>
<a href={getLocalePath('/posts/')}>{t('nav_posts')}</a>
</li>
<li class:list={[pathname === getLocalePath('/about/') && 'active']}>
<a href={getLocalePath('/about/')}>{t('nav_about')}</a>
</li>
<li>
<a href="#">{switcherLabels[locale]}</a>
<ul>
{switcherData.map(item => (
<li>
<a href={`${item.href.replace(/\/$/, '')}/`}>{switcherLabels[item.locale]}</a>
</li>
))}
</ul>
</li>
</ul>
</nav>
</body>
</html>
GraphQL 語系設定
在 GraphQL 請求中設定語系變數,只需在 src/api/index.ts
加入 Content-Language
Header 即可,但需注意的是,前端習慣使用 -
連接語系的格式,後端使用 _
來連接,因此需要轉換過才能使用:
ts
import { getLocale } from 'i18n:astro'
export const graphQLAPI = createGraphQLAPI({
endpoint: `${siteConfig.apiBaseUrl}/graphql`,
fetchOptions: () => ({
headers: {
'Content-Language': getLocale().replace('-', '_'),
},
}),
})
然後在 GraphQL 請求中就會請求對應的語系資料了。
動態參數路由設定
當路由有動態參數時 (例如:src/routes/posts/[slug]
),就需要使用 setDynamicParams()
函數來設定動態參數的語系路由,注意需要放在 graphQLAPI()
的後面,因為要先確保 API 請求成功後才設定動態參數:
ts
import { getLocales, setDynamicParams } from 'i18n:astro'
setDynamicParams(getLocales().map(locale => ({
locale,
params: { slug },
})))