Skip to content

kslstn/astro-i18n-blog-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Astro i18n blog starter

No Maintenance Intended

Live demo

I found that out of the box, the Astro 4.5 blog example and internationalization/localization (i18n) features require quite a bit of work to become a fully working, SEO-optimized and screen reader-friendly blog. This project attempts to make getting started a bit easier.

Caution

I've stopped maintenance of this starter, because:

  1. Keeping this repo updated with Astro's changes takes quit a bit of time, whereas pulling in changes to sites that are based can likely result in merge conflicts.
  2. The way it redefines collection pages' 'slugs' (paths) using getPagePath() and getPostPath() works fine, but I've found that it's convoluted and that it's easier to use file path-based routing instead—even if that involves a slightly complicated glob pattern with the default language not having a path prefix.

Important

There's one feature you may still find interesting to see in this project: finding translations of pages. Other starters often rely on file names to find translations, making it impossible to make locale-specific URLs. In this repo you find that pages can have a reference frontmatter value. MainI18n.astro creates an array of all translations of the current page, based on that value.

Tip

To create the what I called a 'slighly complicated glob pattern' above, you can define the loader (that's an Astro 5 thing) for the blog collection like this:

const bblogCollection = defineCollection({
  loader: glob({
    pattern: "{blog,nl/blog,de/blog}/**/*.{md,mdx}",
    base: "./src/content/",
  }),
  // ...
})

Requirements and goals

  • Use built-in features and reduce additional dependencies where possible. The assumption is that the Astro team will expand i18n features and that parts of this setup can be replaced with built-in functions in the future.
  • Add a minimum of styling and hard-coded settings, so you can quickly get to styling and configuring your own site.
  • Allow for multiple collections (don't abuse collections for localization)
  • Separate layouts, components and content; make sure all content is saved in markdown and data files.
  • Support the features below!

Features

  • ⛓️ Linked translations via a reference property: no need for matching slugs between locales.
  • 🏖️ Allow adding pages for a new locale with minimal effort; use the default locale* as a fallback for missing settings and strings.
  • 🏷️ Content tags á la WordPress
  • 🗺️ Sitemap support with translation links
  • 📡 Localized RSS Feeds
  • 🌍 Customizable URL structure, like domain.tld/locale/directory/slug
  • 🪽 Skip to content link for screen reader and keyboard users
  • 👩‍💼 Localized author profiles from a single data file
  • 🔏 Secret/draft state to exclude posts from rendering
  • 🔚 404 Page not found page
  • 🐭 Ultra minimal styling without CSS classes with new.css (remove only two lines of code to remove it!)
  • 🔗 target="_blank" for external links with Rehype plugin
  • 😉 Separate favicon for dev server to not get confused between dev and production

*) This is why the Dutch demo pages have an English header menu; no Dutch menu items were defined.

Based on the official blog example, this setup still has:

  • ✅ 100/100 Lighthouse performance
  • ✅ SEO-friendly with canonical URLs and OpenGraph data
  • ✅ Markdown & MDX support

🚀 Project Structure

You'll see the following folders and files:

├── public/
├── src/
│   ├── components/
│   ├── content/
│   ├── i18n/
│   │   ├── i18n.ts ← Set up locales here
│   │   ├── uiStrings.js ← Localized headings, labels, etc.
│   │   └── utilities ← i18n-specific functions
│   ├── layouts/
│   ├── styles/
│   ├── utilities/
│   ├── consts.ts ← Settings loaded by astro.config.mjs
│   ├── env.d.ts
│   ├── header.ts ← Settings for header menus, optionally per locale
│   └── people.ts ← Bylines and author profile pages
├── astro.config.mjs
├── README.md
├── package.json
└── tsconfig.json

Astro looks for .astro or .md files in the src/pages/ directory. Each page is exposed as a route based on its file name.

There's nothing special about src/components/, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.

The src/content/ directory contains collections of related markdown and MDX documents. A 'blog' collection has been defined already.

Any static assets, like images, can be placed in the public/ directory.

🧞 Commands

All default commands can be run from the root of the project, from a terminal:

Command Action
pnpm install Installs dependencies
pnpm run dev Starts local dev server at localhost:4321
pnpm run build Build your production site to ./dist/
pnpm run preview Preview your build locally, before deploying
pnpm run astro ... Run CLI commands like astro add, astro check
pnpm run astro -- --help Get help using the Astro CLI

To do

  • Get feedback. This is my third Astro project, but it's I noticed while making this, that I'm very much a novice Astro user. Feel free to contact me and make pull requests.
  • Although there are no errors or known issues, your editor may show a few squiggly lines caused missing/faulty TypeScript settings.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published