astro-lang-i18n
v1.0.0
Published
📦️ Smart multi-dimensional routing for Astro i18n projects.
Maintainers
Readme
- node >= 22.17.0
- bun >= 1.1.0
bun i -D astro-lang-i18nnpm i -D astro-lang-i18npnpm i -D astro-lang-i18nyarn i -D astro-lang-i18nTo start using the package, you have a some options:
- Case 1: use always
/[lang]in your routes, and then use thegetI18nfunction to get the translations for the current language. e.g:/enfor english and/frfor french, but the default language is english, so the route for english will be/enand the route for french will be/fr. therefore, you will have to redirect the user to the correct route based on their language preference, or you can use a middleware to do that for you.
You will end with routes like this: ["/en", "/fr"] and / redirect to /en.
- Case 2: or have your default language as
/[defaultLang]and then have translated routes with/[lang]and use thegetI18nfunction to get the translations for the current language. E.g:/enfor english and/frfor french, but the default language is english, so the route for english will be/and the route for french will be/fr.
You will end with routes like this: ["/", "/fr"] and / will be the default language route.
IMPORTANT: This library is flexible and can adapt to both cases, but you have to choose one of them and stick to it, otherwise you will end with a lot of duplicated routes and a lot of confusion.
Also this library should to be used in modules so you can have different modules with different routes and different translations, yo don`t define a big object with all your routes and all your translations, you can have a module for the landing page, a module for the dashboard, a module for the admin panel, etc... and each module will have its own routes and its own translations.
Routing
Start creating your routes in the landing_router.ts file.
const landingRouter = {
es: {
aboutUs: '/es/sobre-nosotros',
home: '/es'
},
en: {
aboutUs: '/en/about-us',
home: '/en'
},
fr: {
aboutUs: '/fr/a-propos-de-nous',
home: '/fr'
}
};
export { landingRouter };we are going to make for Case 2 translated routes.
Then in your page, you can use the getDynamicLangRoute function to generate the static paths for your page based on the router you defined. e.g: /[lang]/[about_us].astro for the about us page.
---
import { defaultLanguage } from 'src/configuration/language';
import { landingRouter } from 'src/router/landing_router';
import { getDynamicLangRoute } from 'astro-lang-i18n';
export const getStaticPaths = () => {
return getDynamicLangRoute({
mappings: { about_us: 'aboutUs' },
router: landingRouter,
defaultLang: defaultLanguage,
excludeDefaultLang: true
});
};
---
<AboutUsPage />Mapping is used to map the parameter name in the file name to the route key in the router, e.g: about_us in the file name is mapped to aboutUs in the router.
Then you add pages/index.astro for the home page.
---
import LandingPage from 'src/component/landing_page.astro';
import { defaultLanguage } from 'src/configuration/language';
import { landingRouter } from 'src/router/landing_router';
import { getDynamicLangRoute } from 'astro-lang-i18n';
export const getStaticPaths = () => {
return getDynamicLangRoute({
mappings: { home: 'home' },
router: landingRouter,
defaultLang: defaultLanguage,
excludeDefaultLang: true
});
};
---
<LandingPage />And for the about us page you create pages/about_us.astro.
---
import AboutUsPage from 'src/component/about_us_page.astro';
---
<AboutUsPage />If you have more than one page in the same module, you can create a folder for that module and then create the pages inside that folder, e.g: pages/[lang]/[dashboard]/[settings].astro for the settings page in the dashboard module.
This example:
const dashboardRouter = {
en: {
settings: '/en/administrador/settings'
},
es: {
settings: '/es/dashboard/configuracion'
},
fr: {
settings: '/fr/admin/parametres'
}
};
getDynamicLangRoute({
mappings: {
dashboard: 'settings',
settings: 'settings'
},
router: dashboardRouter,
defaultLang: defaultLanguage,
excludeDefaultLang: true
});Result in this
[
{
params: { lang: 'es', dashboard: 'dashboard', settings: 'configuracion' }
},
{
params: { lang: 'fr', dashboard: 'admin', settings: 'parametres' }
}
]Translations
For start and having the language as a global variable, you can use the Astro.locals to get the current language in any component. you need to set the language in the Astro.locals in the src/middleware.ts file, so you can access it in any component.
import { sequence, defineMiddleware } from 'astro:middleware';
import { defaultLanguage, supportedLanguages } from 'src/configuration/language';
import { i18nMiddleware } from 'src/util/i18n_middleware';
const i18nSetup = defineMiddleware(async (context, next) => {
return i18nMiddleware({
context,
next,
defaultLanguage,
supportedLanguages
});
});
const onRequest = sequence(i18nSetup);
export { onRequest };To get the translations for the current language, you can use the getI18n function in your component. e.g: src/component/landing_page.astro.
const landingLocale = {
en: {
title: 'Welcome to our website'
},
es: {
title: 'Bienvenido a nuestro sitio web'
},
fr: {
title: 'Bienvenue sur notre site web'
}
};---
import { landingLocale } from 'src/locales/landing_locale';
import { getI18n } from 'astro-lang-i18n';
const { language } = Astro.locals;
const i18n = getI18n(language, landingLocale);
---
<h1>{i18n.title}</h1>