Itzuli

Astro with i18n

Guide to Astro's i18n: Best Practices and Pitfalls


Introduction

Astro’s native internationalization (i18n) support (introduced in [email protected]) simplifies building internationalized websites. This guide explores best practices, addressing common pitfalls and providing alternative solutions.

Astro provides a i18n recipe explaining how to implement i18n in your Astro project. The recipe is a great starting point, but can lead to some common pitfals.

Don’t use getRelativeLocaleUrl to change current page language

Astro provides a great api to generate dynamic locale URLs using getRelativeLocaleUrl. However, it’s not ideal for switching languages on the same page.

It either redirects to the root page or creates an unexpected double-prefixed URL:

  • Using getRelativeLocaleUrl(locale: string) in your language switcher will redirect you to the root page with the seleceted language.

  • Using getRelativeLocaleUrl("en", Astro.url.pathname) will generate a double-prefixed URL with the current and new language as prefixes e.g. /es/en/blog.

Alternative: Custom changeLanguage Function

To solve this issue, I created a custom function changeLanguage(lang: string, path: string) that will change the current page language and stay on the same page.

src/i18n/utils.ts
LANGUAGES = {
ENGLISH: "en",
SPANISH: "es",
EUSKERA: "eus",
};
export const showDefaultLang = false;
export const defaultLang = LANGUAGES.SPANISH;
export function changeLanguage(lang: string, path: string) {
const languagePrefixes = Object.values(LANGUAGES);
const hasLanguagePrefix = languagePrefixes.some((prefix) =>
path.includes(prefix)
);
if (hasLanguagePrefix) {
path = path.replace(new RegExp(`/${languagePrefixes.join("|")}`), "");
}
return !showDefaultLang && lang === defaultLang ? path : `/${lang}${path}`;
}

showDefaultLang is a boolean that represents if the default language is in the url. This should match your Astro configuration.

defaultLang is the default language of your site. This should match your Astro configuration.

When to Use getRelativeLocaleUrl

This function shines for navigating to different pages in various locales:

<a href={`${getRelativeLocaleUrl(currentLocale, "/blog/i18n-with-astro/")}`} >

This will generate a url with the current locale as a prefix, e.g. /es/blog/i18n-with-astro/ if the current locale is Spanish.

Content Localization Beyond Astro’s i18n Recipe

Astro provides in its i18n recipe a way to show different content for different locales using . However, it’s not always the best solution, speacially for large content.

While the astro i18n recipe offers basic content translation, it might not be optimal for large amounts of text. Consider separate JSON files per language:

src/i18n/index.ts
import english from "./en.json";
import spanish from "./es.json";
import euskera from "./eus.json";
export const getI18N = ({
currentLocale = "es",
}: {
currentLocale: string | undefined;
}) => {
if (currentLocale === LANGUAGES.ENGLISH) return english;
if (currentLocale === LANGUAGES.SPANISH) return spanish;
if (currentLocale === LANGUAGES.EUSKERA) return euskera;
return spanish;
};

Then we can use the getI18N function to get the content for the current locale.

src/pages/index.astro
import { getI18N } from "src/i18n";
const currentLocale = Astro.currentLocale ? Astro.currentLocale : "es";
const i18n = getI18N({ currentLocale });

i18n will contain the content for the current locale.

Conclusion

Astro’s i18n support empowers you to build internationalized websites effectively. By understanding common pitfalls and exploring alternative approaches, you can create seamless user experiences for diverse audiences.