🧪 astro-i18next
An astro integration of i18next + some utility components to help you translate your astro websites!
Status [beta version]
You can use it, and feedback is more than welcome! As integrations in Astro are still experimental, note that some breaking changes may still be introduced during this phase.
Getting started
1. Install
npm install astro-i18next
2. Configure
-
Add
astro-i18next
to yourastro.config.mjs
:import { defineConfig } from "astro/config"; import astroI18next from "astro-i18next"; export default defineConfig({ experimental: { integrations: true, }, integrations: [ astroI18next({ baseLanguage: "en", i18next: { debug: true, // convenient during development to check for missing keys supportedLngs: ["en", "fr"], }, }), ], });
-
Create a
locales
folder containing the translation strings as JSONs (⚠️ files must be named as the language code):src ├-- locales # astro-i18next will load all supported locales | |-- en.json # english translation strings | └-- fr.json # french translation strings └-- pages |-- [lang].astro # you may add a dynamic route to generate language routes └-- index.astro # route for base language
🚀 Start translating
3. You're all set! You may now start translating your website by using
i18next's t
function or the
Trans component depending on your needs.
Here's a quick tutorial to get you going:
---
// src/pages/index.astro
import i18next, { t } from "i18next";
import { Trans, HeadHrefLangs } from "astro-i18next/components";
// Use i18next's changeLanguage() function to change the language
i18next.changeLanguage("fr");
---
<html lang={i18next.language}>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{t("site.title")}</title>
<meta name="description" content={t("site.description")} />
<HeadHrefLangs />
</head>
<body>
<h1>{t("home.title")}</h1>
<p>
<Trans i18nKey="home.subtitle">
This is a <em>more complex</em> string to translate, mixed with <strong
>html elements
</strong> such as <a href="https://example.com/">a cool link</a>!
</Trans>
</p>
</body>
</html>
// src/locales/en.json
{
"site": {
"title": "My awesome website!",
"description": "Here is the description of my awesome website!"
},
"home": {
"title": "Welcome to my awesome website!",
"subtitle": "This is a <0>more complex</0> string to translate, mixed with <1>html elements</1>, such as a <2>a cool link</2>!"
}
}
// src/locales/fr.json
{
"site": {
"title": "Mon super site web !",
"description": "Voici la description de mon super site web !"
},
"home": {
"title": "Bienvenue sur mon super site web !",
"subtitle": "Ceci est une chaine de charactères <0>plus compliquée</0> à traduire, il y a des <1>éléments html</1>, comme <2>un super lien</2> par exemple !"
}
}
For a more exhaustive example, see the demo project.
Utility components
Trans component
A component that takes care of interpolating its children with the translation strings. Inspired by react-i18next's Trans component.
---
import { Trans } from "astro-i18next/components";
---
<Trans i18nKey="superCoolKey">
An <a href="https://astro.build" title="Astro website">astro</a> integration of
<a href="https://www.i18next.com/" title="i18next website">i18next</a> and utility
components to help you translate your astro websites!
</Trans>
// fr.json
{
"superCoolKey": "Une intégration <0>astro</0> d'<1>i18next</1> + quelques composants utilitaires pour vous aider à traduire vos sites astro !"
}
Trans Props
Prop name | Type (default) | Description |
---|---|---|
i18nKey | string (undefined) | Internationalization key to interpolate to. Can contain the namespace by prepending it in the form 'ns:key' (depending on i18next.options.nsSeparator) |
ns | ?string (undefined) | Namespace to use. May also be embedded in i18nKey but not recommended when used in combination with natural language keys. |
interpolate function
interpolate(i18nKey: string, reference: string, namespace: string | null): string
astro-i18next exposes the logic behind the Trans component, you may want to use it directly.
import { interpolate } from "astro-i18next";
const interpolated = interpolate(
"superCoolKey",
'An <a href="https://astro.build" title="Astro website">astro</a> integration of <a href="https://www.i18next.com/" title="i18next website">i18next</a> and utility components to help you translate your astro websites!'
);
LanguageSelector component
Unstyled custom select component to choose amongst supported locales.
---
import { LanguageSelector } from "astro-i18next/components";
---
<LanguageSelector showFlag={true} class="my-select-class" />
LanguageSelector Props
Prop name | Type (default) | Description |
---|---|---|
showFlag | ?boolean (false ) |
Choose to display the language emoji before language name |
HeadHrefLangs component
HTML tags to include in your page's <head>
section to let search engines know
about its language and region variants. To know more, see
Google's advanced localized versions.
---
import i18next from "i18next";
import { HeadHrefLangs } from "astro-i18next/components";
---
<html lang={i18next.language}>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>...</title>
<meta name="description" content="..." />
<HeadHrefLangs />
</head>
<body>...</body>
</html>
The HeadHrefLangs component will generate all of the alternate links depending on the current url and supported languages.
For example, if you are on the /about
page and support 3 languages (en
,
fr
, es
) with en
being the base language, this will render:
<link rel="alternate" hreflang="en" href="https://www.example.com/about/" />
<link rel="alternate" hreflang="fr" href="https://www.example.com/fr/about/" />
<link rel="alternate" hreflang="es" href="https://www.example.com/es/about/" />
localizePath function
localizePath(path: string, locale: string | null = null): string
Sets a path within a given locale. If the locale param is not specified, the current language will be used.
Note: This should be used instead of hard coding paths to other pages. It will take care of setting the right path depending on the locale you set.
---
import { localizePath } from "astro-i18next";
import i18next from "i18next";
i18next.changeLanguage("fr");
---
<a href={localizePath("/about")}>...</a>
<!-- renders: <a href="/fr/about">...</a> -->
localizeUrl function
localizeUrl(url: string, locale: string | null = null): string
Sets a url within a given locale. If the locale param is not specified, the current language will be used.
Note: This should be used instead of hard coding urls for internal links. It will take care of setting the right url depending on the locale you set.
---
import { localizeUrl } from "astro-i18next";
import i18next from "i18next";
i18next.changeLanguage("fr");
---
<a href={localizeUrl("https://www.example.com/about")}>...</a>
<!-- renders: <a href="https://www.example.com/fr/about">...</a> -->
Namespaces
For larger projects, the namespaces feature allows you to break your translations into multiple files, thus easier maintenance!
See i18next's documentation on the Namespaces principle.
1. Configure namespaces
All you have to do is create a folder including the namespaced translation files for each language instead of a single file per language.
astro-i18next
will automagically load the namespaces for you!
src
├-- locales
| ├-- en # the base language `en` contains 3 namespaces
| | ├-- common.json
| | ├-- home.json
| | └-- about.json
| └-- fr # `fr` language must contain the same namespaces as the base `en` language
| ├-- common.json
| ├-- home.json
| └-- about.json
└-- pages
└-- [...]
You can also define the default namespace in your astro-i18next
config:
import { defineConfig } from "astro/config";
import astroI18next from "astro-i18next";
export default defineConfig({
experimental: {
integrations: true,
},
integrations: [
astroI18next({
baseLanguage: "en",
i18next: {
defaultNS: "common", // translation keys will be retrieved in the common.json file by default
supportedLngs: ["en", "fr"],
},
}),
],
});
2. Using namespaces
-
Using i18next's
t
function--- import { t } from "i18next"; --- <p>{t("home:myKey")}</p> or <p>{t("myKey", { ns: "home" })}</p>
-
Using the Trans component
---
import { Trans } from "astro-i18next/components";
---
<Trans i18nKey="myKey" ns="home">This is a sample key</Trans>
Config Props
astro-i18next
abstracts most of the configuration for you so that you don't
have to think about it. Just focus on translating!
Though if you'd like to go further, feel free to tweak the config!
Prop name | Type (default) | Description |
---|---|---|
baseLanguage | string (undefined) | The default language for your website |
resourcesPath | ?string (src/resources/locales/ ) |
The path to your translation files |
i18next |
InitOptions (undefined) |
The i18next configuration. See i18next's documentation to know more |
License
Code released under the MIT License.
Copyright (c) 2022-present, Yassine Doghri (@yassinedoghri)