astro-i18next

An astro integration of i18next + some utility components to help you trans...

README


🧪 astro-i18next


An astro integration of
i18next + some utility components to help you
translate your astro websites!

[![npm-badge]][npm] [![build-badge]][build] [![codecov-badge]][codecov] [![license-badge]][license] [![contributions-badge]][contributions] [![semantic-release-badge]][semantic-release] [![stars-badge]][stars]


Note

>

Status - 🚧 Beta

>

[👉 Road to v1.0.0](https://github.com/yassinedoghri/astro-i18next/issues/19)

>

You can use it, and feedback is more than welcome! Note that some breaking

changes may still be introduced during this phase as the goal for v1 is to get

the best possible DX for translating your Astro pages.


Examples


ExampleStatus
-----------------------------------------------------------------------------------------------------------------------------------------
[SSG[![example-up-badge]](examples/basics)
[SSR[![example-up-badge]](examples/node)
[**React**](examples/react)[![example-up-badge]](examples/react)
[SSR[![example-down-badge]](examples/netlify)
SSR[![example-down-badge]](examples/basics)

  - generate

🚀 Getting started


1. Install


  1. ``` sh
  2. npm install astro-i18next
  3. ```

2. Configure


1. Add astro-i18next to your astro.config.mjs:

  1. ``` js
  2.    import { defineConfig } from "astro/config";
  3.    import astroI18next from "astro-i18next";

  4.    export default defineConfig({
  5.      integrations: [astroI18next()],
  6.    });
  7. ```

2. Configure astro-i18next in your astro-i18next.config.mjs file:

  1. ``` js
  2.    /** @type {import('astro-i18next').AstroI18nextConfig} */
  3.    export default {
  4.      defaultLocale: "en",
  5.      locales: ["en", "fr"],
  6.    };
  7. ```

   ℹ️ Your astro-i18next config file can be a javascript (.js | .mjs |
   .cjs) or typescript (.ts | .mts | .cts) file.

   ℹ️ For a more advanced configuration, see the

3. By default, astro-i18next expects your translations to be organized inside
   your
   [astro's publicDir](https://docs.astro.build/en/reference/configuration-reference/#publicdir),
   in a locales folder:

  1. ``` sh
  2.      public
  3.      locales  # create this folder to store your translation strings
  4.          en
  5.          |   translation.json
  6.          fr
  7.              translation.json
  8. ```

   ℹ️ astro-i18next loads your translation files both server-side and
   client-side using
   plugins.

   ℹ️ You may choose to organize your translations into multiple files instead
   of a single file per locale using namespaces.

3. Start translating


You may now start translating your pages by using
[i18next's t function](https://www.i18next.com/overview/api#t) or the
Trans component depending on your needs.

Here's a quick tutorial to get you going:

1. Use translation keys in your Astro pages

  1. ```astro
  2.    ---
  3.    // src/pages/index.astro
  4.    import i18next, { t } from "i18next";
  5.    import { Trans, HeadHrefLangs } from "astro-i18next/components";
  6.    ---

  7.    <html lang={i18next.language}>
  8.      <head>
  9.        <meta charset="utf-8" />
  10.        <meta name="viewport" content="width=device-width" />
  11.        <title>{t("site.title")}</title>
  12.        <meta name="description" content={t("site.description")} />
  13.        <HeadHrefLangs />
  14.      </head>
  15.      <body>
  16.        <h1>{t("home.title")}</h1>
  17.        <p>
  18.          <Trans i18nKey="home.subtitle">
  19.            This is a <em>more complex</em> string to translate, mixed with <strong
  20.              >html elements
  21.            </strong> such as /example.com/">a cool link</a>!
  22.          </Trans>
  23.        </p>
  24.      </body>
  25.    </html>
  26. ```




  1. ``` sh
  2.    npx astro-i18next generate
  3. ```

3. You're all set! Have fun translating and generate localized pages as you go
   🚀

Note

>

For a real world example, see the demo project or try the _Astro

i18n basics example_ on StackBlitz:\

Open in StackBlitz



💻 CLI commands


generate


  1. ``` sh
  2. npx astro-i18next generate
  3. ```

This command will generate localized pages depending on your config and set
i18next's language change on each page.

For instance, with locales = ["en", "fr", "es"], and "en" being the default
locale and having:

  1. ``` sh
  2. src
  3. pages
  4.      about.astro
  5.      index.astro
  6. ```

👇 Running npx astro-i18next generate will create the following pages

  1. ``` sh
  2. src
  3. pages
  4.      es
  5.     |   about.astro
  6.     |   index.astro
  7.      fr
  8.     |   about.astro
  9.     |   index.astro
  10.      about.astro
  11.      index.astro
  12. ```

🔄 Translate Routes


astro-i18next let's you translate your pages routes for each locale!

For instance, with support for 3 locales (en, fr, es), en being the
default and the following pages:

  1. ``` sh
  2. src
  3. pages
  4.      about.astro
  5.      contact-us.astro
  6.      index.astro
  7. ```

1. Set route mappings in your astro-i18next config:

  1. ``` js
  2.    /** @type {import('astro-i18next').AstroI18nextConfig} */
  3.    export default {
  4.      defaultLocale: "en",
  5.      locales: ["en", "fr", "es"],
  6.      routes: {
  7.       fr: {
  8.         "about": "a-propos",
  9.         "contact-us": "contactez-nous",
  10.         "products": {
  11.           "index": "produits",
  12.           "categories": "categories",
  13.         }
  14.       }
  15.       es: {
  16.         "about": "a-proposito",
  17.         "contact-us": "contactenos",
  18.         "products": {
  19.           "index": "productos",
  20.           "categories": "categorias",
  21.         }
  22.       }
  23.      },
  24.    };
  25. ```

2. Generate your localized pages using the generate CLI command,
   they will be translated for you!

  1. ``` sh
  2. src
  3. pages
  4.      es
  5.     |   productos
  6.     |   |   categorias.astro
  7.     |   |   index.astro
  8.     |   a-proposito.astro
  9.     |   contactenos.astro
  10.     |   index.astro
  11.      fr
  12.     |   produits
  13.     |   |   categories.astro
  14.     |   |   index.astro
  15.     |   a-propos.astro
  16.     |   contactez-nous.astro
  17.     |   index.astro
  18.      products
  19.     |   categories.astro
  20.     |   index.astro
  21.      about.astro
  22.      contact-us.astro
  23.      index.astro
  24. ```

Note

>

localizeUrl utility functions will retrieve the

correct route based on your mappings.



📦 Utility components


Trans component


A component that takes care of interpolating its children with the translation
strings. Inspired by

  1. ```astro
  2. ---
  3. import { Trans } from "astro-i18next/components";
  4. ---

  5. <Trans i18nKey="superCoolKey">
  6.   An <a href="https://astro.build" title="Astro website">astro</a> integration of
  7.   <a href="https://www.i18next.com/" title="i18next website">i18next</a> and utility
  8.   components to help you translate your astro websites!
  9. </Trans>
  10. ```

  1. ``` json
  2. // fr.json
  3. {
  4.   "superCoolKey": "Une intégration <0>astro</0> d'<1>i18next</1> + quelques composants utilitaires pour vous aider à traduire vos sites astro !"
  5. }
  6. ```

Trans Props


PropTypeDescription
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
i18nKey?stringInternationalization
ns?stringNamespace

LanguageSelector component


Unstyled custom select component to choose amongst supported locales.

  1. ```astro
  2. ---
  3. import { LanguageSelector } from "astro-i18next/components";
  4. ---

  5. <LanguageSelector showFlag={true} class="my-select-class" />
  6. ```

LanguageSelector Props


PropTypeDescription
------------------------------------------------------------------------------------
showFlag?booleanChoose

HeadHrefLangs component


HTML tags to include in your page's `` section to let search engines know
about its language and region variants. To know more, see

  1. ```astro
  2. ---
  3. import i18next from "i18next";
  4. import { HeadHrefLangs } from "astro-i18next/components";
  5. ---

  6. <html lang={i18next.language}>
  7.   <head>
  8.     <meta charset="utf-8" />
  9.     <meta name="viewport" content="width=device-width" />
  10.     <title>...</title>
  11.     <meta name="description" content="..." />
  12.     <HeadHrefLangs />
  13.   </head>
  14.   <body>...</body>
  15. </html>
  16. ```

The HeadHrefLangs component will generate all of the alternate links depending
on the current url and supported locales.

For example, if you are on the /about page and support 3 locales (en, fr,
es) with en being the default locale, this will render:

  1. ``` html
  2. <link rel="alternate" hreflang="en" href="https://www.example.com/about/" />
  3. <link rel="alternate" hreflang="fr" href="https://www.example.com/fr/about/" />
  4. <link rel="alternate" hreflang="es" href="https://www.example.com/es/about/" />
  5. ```

📦 Utility functions


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.

  1. ```ts
  2. import { interpolate } from "astro-i18next";

  3. const interpolated = interpolate(
  4.   "superCoolKey",
  5.   'An astro integration of i18next and utility components to help you translate your astro websites!'
  6. );
  7. ```

localizePath function


localizePath(path: string, locale: string | null = null, base: string = import.meta.env.BASE_URL): string

Sets a path within a given locale. If the locale param is not specified, the
current locale 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.


  1. ```astro
  2. ---
  3. import { localizePath } from "astro-i18next";
  4. import i18next from "i18next";

  5. i18next.changeLanguage("fr");
  6. ---

  7. <a href={localizePath("/about")}>...</a>

  8. ```

localizeUrl function


localizeUrl(url: string, locale: string | null = null, base: string = import.meta.env.BASE_URL): string

Sets a url within a given locale. If the locale param is not specified, the
current locale 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.


  1. ```astro
  2. ---
  3. import { localizeUrl } from "astro-i18next";
  4. import i18next from "i18next";

  5. i18next.changeLanguage("fr");
  6. ---

  7. <a href={localizeUrl("https://www.example.com/about")}>...</a>

  8. ```


👀 Going further


Namespaces


i18next allows you to organize your translation keys into

You can have as many namespaces as you wish, have one per page and one for
common translation strings for example:

  1. ``` sh
  2. public
  3. -- locales
  4. |   |-- en
  5. |   |   |-- about.json    # "about" namespace
  6. |   |   |-- common.json   # "common" namespace
  7. |   |   -- home.json     # "home" namespace
  8. |   -- fr   # same files in other locale folders
  9. src
  10. -- pages
  11.       |-- about.astro
  12.       -- index.astro
  13. ```

1. It can easily be setup using the namespaces and defaultNamespace keys,
   like so:

  1. ```ts
  2.    /** @type {import('astro-i18next').AstroI18nextConfig} */
  3.    export default {
  4.      defaultLocale: "en",
  5.      locales: ["en", "fr"],
  6.      namespaces: ["about", "common", "home"],
  7.      defaultNamespace: "common",
  8.    };
  9. ```

2. Load the namespace globally using i18next.setDefaultNamespace(ns: string)
   or specify it in the t function or the Trans component:

  1. ```astro
  2.    ---
  3.    import { t, setDefaultNamespace } from "i18next";
  4.    import { Trans } from "astro-i18next/components";

  5.    setDefaultNamespace("home");
  6.    ---

  7.    <h1>{t("myHomeTitle")}</h1>
  8.    <p>
  9.      <Trans i18nKey="myHomeDescription">
  10.        This translation is loaded from the default <strong>home</strong> namespace!
  11.      </Trans>
  12.    </p>
  13.    <p>
  14.      <Trans i18nKey="myCommonCTA" ns="common">
  15.        This translation is loaded from the <strong>common</strong> namespace!
  16.      </Trans>
  17.    </p>
  18.   
  19.    <button>{t("common:buttonCTA")}</button>
  20. ```

AstroI18nextConfig Props


astro-i18next's goal is to abstract 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 in customizing i18next, feel free to tweak
your config!

PropTypeDescription
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
defaultLocale`string`The
locales`string[]`Your
namespaces`string`String
defaultNamespace`string`Default
load`Array<"server"Load
i18nextServer`?InitOptions`The
i18nextServerPlugins`?{[key:Set
i18nextClient`?InitOptions`The
i18nextClientPlugins`?{[key:Set
routes`[segment:The
showDefaultLocale`boolean`(`false`)Whether

✨ Contributors


Thanks goes to these wonderful people




Yassine Doghri
Yassine Doghri

💻 📖 🤔 🎨 💡 🚧
Davide Ceschia
Davide Ceschia

💻 🐛
preetamslot
preetamslot

🐛
Dmytro
Dmytro

🐛
Campbell He
Campbell He

🐛
MelKam
MelKam

💻
L1lith
L1lith

🐛 🤔
Anomander43
Anomander43

📖
Dominik Schöni
Dominik Schöni

💻
Dalibor Hon
Dalibor Hon

💻 🐛
Oleksii Lozoviahin
Oleksii Lozoviahin

💻
Alessandro Talamona
Alessandro Talamona

🐛
Josh Kramer
Josh Kramer

💻 🐛
Alexandre Fernandez
Alexandre Fernandez

💻 🐛






This project follows the
specification. Contributions of any kind welcome!

❤️ Acknowledgments


This wouldn't have been possible without the awesome work from the
Locize and Astro teams.

Inspired by some of the greatly thought-out i18n implementations:


📜 License


Code released under the MIT License.

Copyright (c) 2022-present, Yassine Doghri

[npm]: https://www.npmjs.com/package/astro-i18next
[npm-badge]: https://img.shields.io/npm/v/astro-i18next
[build]:
  https://github.com/yassinedoghri/astro-i18next/actions/workflows/publish.yml
[build-badge]:
  https://img.shields.io/github/workflow/status/yassinedoghri/astro-i18next/astro-i18next-publish
[license]:
  https://github.com/yassinedoghri/astro-i18next/blob/develop/LICENSE.md
[license-badge]:
  https://img.shields.io/github/license/yassinedoghri/astro-i18next?color=blue
[contributions]: https://github.com/yassinedoghri/astro-i18next/issues
[contributions-badge]:
  https://img.shields.io/badge/contributions-welcome-blueviolet.svg
[semantic-release]: https://github.com/semantic-release/semantic-release
[semantic-release-badge]:
  https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
[stars]: https://github.com/yassinedoghri/astro-i18next/stargazers
[stars-badge]:
  https://img.shields.io/github/stars/yassinedoghri/astro-i18next?style=social
[codecov]: https://codecov.io/gh/yassinedoghri/astro-i18next
[codecov-badge]:
  https://codecov.io/gh/yassinedoghri/astro-i18next/branch/develop/graph/badge.svg?token=IFWNB6UJDJ
[example-up-badge]: https://img.shields.io/badge/status-up-brightgreen
[example-down-badge]: https://img.shields.io/badge/status-down-red