feat: add internationalization support with Spanish and English translations
This commit is contained in:
+18
-9
@@ -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()],
|
||||
},
|
||||
});
|
||||
vite: {
|
||||
plugins: [tailwindcss()],
|
||||
},
|
||||
|
||||
i18n: {
|
||||
locales: ["es", "en"],
|
||||
defaultLocale: "es",
|
||||
routing: {
|
||||
prefixDefaultLocale: false,
|
||||
redirectToDefaultLocale: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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!",
|
||||
},
|
||||
};
|
||||
@@ -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<string, unknown>} 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<string, unknown>, path: string): string | undefined {
|
||||
return path
|
||||
.split(".")
|
||||
.reduce<unknown>(
|
||||
(acc, part) =>
|
||||
acc && typeof acc === "object" ? (acc as Record<string, unknown>)[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<T extends keyof typeof labels>(lang: T) {
|
||||
return (key: string): string => {
|
||||
return getNestedValue(labels[lang], key) ?? getNestedValue(labels[defaultLang], key) ?? key;
|
||||
};
|
||||
}
|
||||
@@ -6,10 +6,11 @@ export interface Props {
|
||||
description: string;
|
||||
}
|
||||
const { title, description } = Astro.props;
|
||||
const currentLang = Astro.currentLocale || "es";
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang={currentLang}>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
@@ -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);
|
||||
---
|
||||
|
||||
<Layout
|
||||
title={translateLabels("metadata.title")}
|
||||
description={translateLabels("metadata.description")}
|
||||
>
|
||||
<div>{translateLabels("title")}</div>
|
||||
</Layout>
|
||||
@@ -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);
|
||||
---
|
||||
|
||||
<Layout title="Home" description="This is the home page">
|
||||
<div>Hello!</div>
|
||||
<Layout
|
||||
title={translateLabels("metadata.title")}
|
||||
description={translateLabels("metadata.description")}
|
||||
>
|
||||
<div>{translateLabels("title")}</div>
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user