Skip to content

Commit 3495b92

Browse files
author
Darío Espinoza
committed
feat: Implement language switcher and enhance internationalization support in Footer and Header components
1 parent 973af6a commit 3495b92

6 files changed

Lines changed: 92 additions & 39 deletions

File tree

components/Footer.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import { PageProps } from "$fresh/server.ts";
2-
import AnchorLang from "../islands/AnchorLang.tsx";
32
import translations from "../locales/es.json" with { type: "json" };
43
interface State {
54
state: { lang: string; translations: typeof translations };
65
}
76
export default function Footer({ state }: PageProps<State>) {
87
const { lang: _lang, translations } = state;
98
return (
10-
<footer class="text-center text-xs w-full py-1 mt-10">
11-
<AnchorLang />
9+
<footer class="text-center text-xs w-full py-1 mt-10 mb-20">
1210
<div
1311
class="py-1"
1412
dangerouslySetInnerHTML={{

components/Header.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,31 @@
11
import DarkMode from "../islands/DarkMode.tsx";
22
export default function Header() {
33
return (
4-
<header class="min-w-min px-4 py-2 rounded-lg max-w-min mx-auto flex gap-4 items-center bg-slate-200/50 left-1/2 -translate-x-1/2 fixed bottom-4 md:sticky md:top-4 z-50 backdrop-blur-md dark:bg-slate-800/50 print:hidden">
5-
<a
4+
<header class="min-w-min px-4 py-2 rounded-lg max-w-min mx-auto flex gap-4 items-center bg-slate-300/40 left-1/2 -translate-x-1/2 fixed bottom-4 md:sticky md:top-4 z-50 backdrop-blur-md dark:bg-slate-700/40 print:hidden">
5+
<a
6+
href="https://github.com/darioesp/vide-coding"
7+
target="_blank"
8+
rel="noopener noreferrer"
9+
>
10+
<svg
11+
aria-hidden="true"
12+
height="18"
13+
viewBox="0 0 16 16"
14+
version="1.1"
15+
width="18"
16+
data-view-component="true"
17+
fill="currentColor"
18+
className="w-[21px] h-[21px]"
19+
>
20+
<path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z">
21+
</path>
22+
</svg>
23+
</a>
24+
<a
625
href="https://github.com/darioesp"
726
target="_blank"
8-
rel="noopener noreferrer">
27+
rel="noopener noreferrer"
28+
>
929
<svg
1030
height="20"
1131
aria-hidden="true"

islands/AnchorLang.tsx

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import { useState, useEffect } from "preact/hooks";
2-
3-
const AnchorLang = () => {
4-
const [lang, setLang] = useState("");
5-
const [switchLang, setSwitchLang] = useState({
6-
lang: "es",
7-
href: "/",
8-
});
9-
useEffect(() => {
10-
const userLang = navigator.language || navigator.userLanguage;
11-
setLang(userLang.split("-").at(0) || "es");
12-
const currentPath = window.location.pathname;
13-
const isEnglish = currentPath.startsWith("/en");
14-
setSwitchLang({
15-
lang: isEnglish ? "es" : "en",
16-
href: isEnglish ? "/" : "/en",
17-
});
18-
19-
}, []);
20-
return (
21-
<a href={switchLang?.href} class="fixed bottom-10 right-10 z-50">
22-
<span class="bg-slate-300/50 text-pink-600 backdrop-blur-sm inline-flex text-xl p-3 font-bold rounded-full justify-center items-center aspect-square min-w-5 min-h-5 size-[48px]">
23-
{ switchLang?.lang }
1+
interface AnchorLangProps {
2+
lang: string;
3+
languages: string[];
4+
}
5+
const AnchorLang = ({ lang: currentLang, languages }: AnchorLangProps) => {
6+
return (
7+
<ul class="fixed bottom-10 right-10 z-50 bg-slate-300/40 dark:bg-slate-700/40 backdrop-blur-sm rounded-lg px-2 py-1.5">
8+
{languages.map((lang: string, index: number) => {
9+
const isActive = lang === (currentLang ?? "es");
10+
<li key={index}>
11+
<a
12+
href={`/${lang}`}
13+
class="flex flex-col justify-center items-center"
14+
>
15+
<span
16+
class={`${
17+
isActive ? "bg-white/70 dark:bg-black/70" : ""
18+
} text-black/60 dark:text-white/60 inline-flex text-xl px-2 py-1.5 font-bold rounded-md justify-center items-center aspect-video max-w-min`}
19+
>
20+
{lang}
2421
</span>
25-
</a>
26-
)
22+
</a>
23+
</li>;
24+
})}
25+
</ul>
26+
);
2727
};
28-
export default AnchorLang;
28+
export default AnchorLang;

routes/[lang]/index.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
1-
import { PageProps } from "$fresh/server.ts";
1+
import { Handlers, PageProps } from "$fresh/server.ts";
22
import Footer from "../../components/Footer.tsx";
33
import Header from "../../components/Header.tsx";
44
import SectionWrapperContent from "../../components/SectionWrapperContent.tsx";
55
import WrapperPage from "../../components/WrapperPage.tsx";
6+
import AnchorLang from "../../islands/AnchorLang.tsx";
67
import translations from "../../locales/es.json" with { type: "json" };
8+
import { getLanguages } from "../../utils/global.ts";
9+
10+
export const handler: Handlers = {
11+
async GET(_, ctx) {
12+
const languages = await getLanguages(); // Obtén los lenguajes en el servidor
13+
return ctx.render({ languages });
14+
},
15+
};
716

817
interface State {
918
state: { lang: string; translations: typeof translations };
19+
languages: string[];
1020
}
1121

12-
export default function Home({ state }: PageProps<State>) {
13-
const { lang: _lang, translations } = state;
22+
export default function Home({ state, data }: PageProps<State>) {
23+
const { lang, translations } = state;
24+
const { languages } = data;
1425
return (
1526
<>
1627
<Header />
@@ -48,8 +59,9 @@ export default function Home({ state }: PageProps<State>) {
4859
</section>
4960
</SectionWrapperContent>
5061
</WrapperPage>
51-
<Footer state={state}/>
5262
</div>
63+
<Footer state={state}/>
64+
<AnchorLang lang={lang} languages={languages} />
5365
</>
5466
);
5567
}

routes/index.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
1-
import { PageProps } from "$fresh/server.ts";
1+
import { Handlers, PageProps } from "$fresh/server.ts";
22
import Footer from "../components/Footer.tsx";
33
import Header from "../components/Header.tsx";
44
import SectionWrapperContent from "../components/SectionWrapperContent.tsx";
55
import WrapperPage from "../components/WrapperPage.tsx";
6+
import AnchorLang from "../islands/AnchorLang.tsx";
67
import translations from "../locales/es.json" with { type: "json" };
8+
import { getLanguages } from "../utils/global.ts";
9+
10+
export const handler: Handlers = {
11+
async GET(_, ctx) {
12+
const languages = await getLanguages(); // Obtén los lenguajes en el servidor
13+
return ctx.render({ languages });
14+
},
15+
};
716

817
interface State {
918
state: { lang: string; translations: typeof translations };
19+
languages: string[];
1020
}
1121

12-
export default function Home({ state }: PageProps<State>) {
22+
export default function Home({ state, data }: PageProps<State>) {
1323
const { lang, translations } = state;
24+
const { languages } = data;
1425
return (
1526
<>
1627
<Header />
@@ -45,8 +56,9 @@ export default function Home({ state }: PageProps<State>) {
4556
</section>
4657
</SectionWrapperContent>
4758
</WrapperPage>
48-
<Footer state={state}/>
4959
</div>
60+
<Footer state={state}/>
61+
<AnchorLang lang={lang} languages={languages} />
5062
</>
5163
);
5264
}

utils/global.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const getLanguages = async () => {
2+
const locales = [];
3+
const files = Deno.readDir("./locales");
4+
for await (const file of files) {
5+
if (file.isFile && file.name.endsWith(".json")) {
6+
const lang = file.name.split(".")[0];
7+
locales.push(lang);
8+
}
9+
}
10+
return locales;
11+
};

0 commit comments

Comments
 (0)