From 4368b5ce316f2f0acbf2df006102ff2006a84cd0 Mon Sep 17 00:00:00 2001 From: jpiere-vailos Date: Mon, 17 Mar 2025 13:12:00 -0500 Subject: [PATCH] feat: add internationalization support with Spanish and English translations --- astro.config.mjs | 27 ++++++++++++++++++--------- src/i18n/ui.ts | 21 +++++++++++++++++++++ src/i18n/utils.ts | 33 +++++++++++++++++++++++++++++++++ src/layouts/Layout.astro | 3 ++- src/pages/en/index.astro | 14 ++++++++++++++ src/pages/index.astro | 11 +++++++++-- 6 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 src/i18n/ui.ts create mode 100644 src/i18n/utils.ts create mode 100644 src/pages/en/index.astro diff --git a/astro.config.mjs b/astro.config.mjs index 15e9c3b8..41e8cacd 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -9,14 +9,23 @@ import tailwindcss from "@tailwindcss/vite"; // https://astro.build/config export default defineConfig({ - integrations: [svelte()], - output: "server", + integrations: [svelte()], + output: "server", - adapter: node({ - mode: "standalone", - }), + adapter: node({ + mode: "standalone", + }), - vite: { - plugins: [tailwindcss()], - }, -}); \ No newline at end of file + vite: { + plugins: [tailwindcss()], + }, + + i18n: { + locales: ["es", "en"], + defaultLocale: "es", + routing: { + prefixDefaultLocale: false, + redirectToDefaultLocale: true, + }, + }, +}); diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts new file mode 100644 index 00000000..17c111c7 --- /dev/null +++ b/src/i18n/ui.ts @@ -0,0 +1,21 @@ +export const languagesList = { + es: "Español", + en: "English", +}; + +export const labels = { + es: { + metadata: { + title: "Inicio", + description: "Página de inicio", + }, + title: "Hola!", + }, + en: { + metadata: { + title: "Home", + description: "Home page", + }, + title: "Hello!", + }, +}; diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts new file mode 100644 index 00000000..aa24161d --- /dev/null +++ b/src/i18n/utils.ts @@ -0,0 +1,33 @@ +import { labels } from "./ui"; + +const defaultLang = "es"; + +/** + * Retrieves a nested value from an object using a dot-separated path. + * + * @param {Record} obj - The object to search within. + * @param {string} path - The dot-separated path to the desired value. + * @returns {string | undefined} - The retrieved value or `undefined` if not found. + */ +function getNestedValue(obj: Record, path: string): string | undefined { + return path + .split(".") + .reduce( + (acc, part) => + acc && typeof acc === "object" ? (acc as Record)[part] : undefined, + obj, + ) as string | undefined; +} + +/** + * Hook to retrieve a translation function based on the selected language. + * + * @template T - The key of the language within the `labels` object. + * @param {T} lang - The language code to use for translations. + * @returns {(key: string) => string} - A function that takes a translation key and returns the translated string. + */ +export function useTranslations(lang: T) { + return (key: string): string => { + return getNestedValue(labels[lang], key) ?? getNestedValue(labels[defaultLang], key) ?? key; + }; +} diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index fab02076..563a0b11 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -6,10 +6,11 @@ export interface Props { description: string; } const { title, description } = Astro.props; +const currentLang = Astro.currentLocale || "es"; --- - + diff --git a/src/pages/en/index.astro b/src/pages/en/index.astro new file mode 100644 index 00000000..643d8059 --- /dev/null +++ b/src/pages/en/index.astro @@ -0,0 +1,14 @@ +--- +import type { languagesList } from "../../i18n/ui"; +import { useTranslations } from "../../i18n/utils"; +import Layout from "../../layouts/Layout.astro"; +const currentLang = Astro.currentLocale || "es"; +const translateLabels = useTranslations(currentLang as keyof typeof languagesList); +--- + + +
{translateLabels("title")}
+
diff --git a/src/pages/index.astro b/src/pages/index.astro index afe8d052..b67ce684 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,7 +1,14 @@ --- +import type { languagesList } from "../i18n/ui"; +import { useTranslations } from "../i18n/utils"; import Layout from "../layouts/Layout.astro"; +const currentLang = Astro.currentLocale || "es"; +const translateLabels = useTranslations(currentLang as keyof typeof languagesList); --- - -
Hello!
+ +
{translateLabels("title")}