onwidget / astrowind

⭕️ AstroWind: A free template using Astro 4.0 and Tailwind CSS. Astro starter theme.
https://astrowind.vercel.app
MIT License
3.36k stars 1.03k forks source link

Internationalization #18

Closed wiledusc closed 2 years ago

wiledusc commented 2 years ago

Hey guys, I'm creating a blog with this template and I would like to know how to add the same posts in different languages.

prototypa commented 2 years ago

Hello @wiledusc,

The Internalization (i18n) is something pending. We had given it a low priority assuming that few people could need it, but no. Since you published the issue I've been thinking about it, but to give you a detailed and generic solution we need time to develop and test it.

For now, if you give some details we can talk about a solution that suits your needs. For this, the following doubts come to me mind:

wiledusc commented 2 years ago

How are you translating the pages that are not Posts? Right now I'm just creating the blog in English, but I want to use the astro-i18next.

Do you plan to add languages ​​over time or have you defined the limit number of languages ​​you want to translate into? I plan to have only Portuguese and English.

Are the posts still loaded from src/data/posts folder or are loaded from an API? Right now they are loaded froms rc/data/posts folder, but I'm planning to load from an API.

prototypa commented 2 years ago

Hi @wiledusc

Here some changes that could work to make your blog multilingual (en, pt). These are ideas that I propose to you assuming that you do not use astro-i18next, you do not need many page translations and you are focused on the posts.

On these days I will make some updates to the template so that it becomes part of the AstroWind core.

Assuming you want the urls like this:

Project structure

From:

│   ├── data/
|   |   └── posts/
|   |       ├── post-slug-1.md
|   |       └── ...
│   ├── pages/
│   |   ├── [blog]/
|   |   |   ├── [...page].astro
|   |   |   └── [slug].astro

To:

│   ├── data/
|   |   └── posts/
+   |       ├── en/
|   |       |   ├── english-post-slug-1.md
|   |       |   └── ...
+   |       └── pt/
|   |           ├── portuguese-post-slug-1.md
|   |           └── ...
│   ├── pages/
+   |   ├── [lang]/
│   |   |   └── [blog]/
|   |   |       ├── [...page].astro
|   |   |       └── [slug].astro

Note: The new folders in data are just for organizing the posts by language, it is not functionally necessary.


Frontmatter code inside Posts

From:

---
pubDate: "Aug 08 2022"
title: "AstroWind template in depth"
description: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus"
...

To:

---
pubDate: "Aug 08 2022"
title: "AstroWind template in depth"
description: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus"
...
+lang: en
+alternate:
+  - hreflang: pr
+    href: portuguese-post-slug-1

Note: Do not include the "+" sign


Changes in .astro pages related to Blog

Note: First you need to go to this file src/utils/getNormalizedPosts.js and add the mapping of the new frontmatter variables: lang and alternate

[slug].astro

From:

/// (...)
export async function getStaticPaths() {
  const posts = await fetchPosts();
  return posts.map((post) => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

To:

/// (...)
export async function getStaticPaths() {
  const posts = await fetchPosts();
  return posts.map((post) => ({
    params: {
      slug: post.slug,
+     lang: post.lang
    },
    props: { post },
  }));
}
/// (...)

Also you need to get the alternates extracted from the frontmatter of the post and add them to the meta tags of the HTML.

[...post].astro

/// (...)
export async function getStaticPaths({ paginate }) {
  const posts = await fetchPosts();

  return paginate(posts, {
    pageSize: BLOG.postsPerPage,
  });
}
/// (...)
/// (...)
export async function getStaticPaths({ paginate }) {
  const posts = await fetchPosts();
  const postsGroupedByLang = await someSmartFunction(posts);

  return Object.keys(postsGroupedByLang).map( lang => 
    paginate(postsGroupedByLang[lang], {
      params: { lang },
      pageSize: BLOG.postsPerPage,
    })
  );
}
/// (...)

In addition to all this you should also review making changes to the menu (change language), detect default language, SEO aspects, add the lang attribute to the main HTML tag, etc etc.

wiledusc commented 2 years ago

Thanks, It worked!