iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0

Astro doesn’t have built-in internationalization (i18n) support, but you can build your own i18n solution. In this recipe, you’ll learn how to use content collections and dynamic routing to serve content for different languages.

This example serves each language at its own subpath, e.g. example.com/en/blog for English and example.com/fr/blog for French.

If you prefer the default language to not be visible in the URL unlike other languages, there are instructions to hide the default language below.

Set up pages for each language

  1. Create a directory for each language you want to support. For example, en/ and fr/ if you are supporting English and French:

folder structure

src
└─ pages
    ├─ en
    │  ├─about.astro
    │  └─index.astro
    ├─ tw
    │  ├─about.astro
    │  └─index.astro
    └─ index.astro
  1. Set up src/pages/index.astro to redirect to your default language.

for SSG

// src/pages/index.astro
---
---
<meta http-equiv="refresh" content="0;url=/en/" />

for SSR

---
return Astro.redirect('/en/');
---

Use collections for translated content

  1. Create a folder in src/content/ for each type of content you want to include and add subdirectories for each supported language. For example, to support English and French blog posts:
src
└─ content
      └─ blog
          ├─ en
          │   ├─post-1.md
          │   └─post-2.md
          ├─ tw
          │   ├─post-1.md
          │   └─post-2.md
          └─ index.astro
  1. Create a src/content/config.ts file and export a collection for each type of content.
// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blogCollection = defineCollection({
  schema: z.object({
    title: z.string(),
    author: z.string(),
    date: z.date()
  })
});

export const collections = {
  'blog': blogCollection
};
  1. Use dynamic routes to fetch and render content based on a lang and a slug parameter.
// src/pages/[lang]/blog/[...slug].astro
---
import { getCollection } from 'astro:content'

export async function getStaticPaths() {
  const pages = await getCollection('blog')

  const paths = pages.map(page => {
    const [lang, ...slug] = page.slug.split('/');
    return { params: { lang, slug: slug.join('/') || undefined }, props: page }
  })

  return paths;
}

const { lang, slug } = Astro.params;
const page = Astro.props;
const formattedDate = page.data.date.toLocaleString(lang);

const { Content } = await page.render();
---
<h1>{page.data.title}</h1>
<p>by {page.data.author} • {formattedDate}</p>
<Content/>

參考資料


上一篇
[Day 18] Strapi & Astro
下一篇
# [Day 20] Astro with Docker
系列文
Micro-Frontend 的新夥伴:Astro.js 的應用與研究20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言