feat: add language switcher

finxol.io f19fc912 3f1cde7d

verified
Changed files
+78 -28
src
+4 -5
astro.config.mjs
···
// @ts-check
import { defineConfig } from "astro/config";
import deno from "@deno/astro-adapter";
+
import preact from "@astrojs/preact";
import icon from "astro-icon";
+
import { config } from "./src/config.ts";
// https://astro.build/config
export default defineConfig({
site: "https://staging.colinozanne.fr",
output: "server",
adapter: deno(),
-
integrations: [icon()],
+
integrations: [preact(), icon()],
i18n: {
locales: ["en", "fr"],
defaultLocale: "fr",
routing: {
prefixDefaultLocale: false,
},
-
domains: {
-
fr: "https://staging.colinozanne.fr",
-
en: "https://staging.colinozanne.co.uk",
-
},
+
domains: config.domains,
},
});
+6
src/config.ts
···
+
export const config = {
+
domains: {
+
fr: "https://staging.colinozanne.fr",
+
en: "https://staging.colinozanne.co.uk",
+
},
+
} as const;
+68 -23
src/layouts/Layout.astro
···
import "@/assets/styles/main.css";
import "@/assets/styles/reset.css";
import { Icon } from "astro-icon/components";
+
import { config } from "@/config.ts";
import colinPng from "@/assets/img/colin.png";
import colinWebp from "@/assets/img/colin.webp";
+
+
const path = Astro.originPathname.replace(/\/(fr|en)\//, "/");
+
const locale = Astro.currentLocale;
---
<!doctype html>
···
</head>
<body>
<header>
-
<picture>
+
<picture class="container">
<source srcset={colinWebp.src} type="image/webp" />
<img src={colinPng.src} alt="Colin Ozanne" />
</picture>
-
<h1>Colin <br class="desktop-only" /> Ozanne</h1>
-
<p>Étudiant M1 Informatique</p>
+
<h1 class="container">Colin <br class="desktop-only" /> Ozanne</h1>
+
<p class="container">Étudiant M1 Informatique</p>
</header>
-
<main class="content-grid">
+
<main class="">
<slot />
</main>
<footer>
+
<div class="container lang-switcher">
+
<a
+
class={locale === "en" ? "active" : ""}
+
href={`${config.domains.en}${path}`}
+
target="_self"
+
>
+
EN
+
</a>
+
<Icon name="pixel:globe" />
+
<a
+
class={locale === "fr" ? "active" : ""}
+
href={`${config.domains.fr}${path}`}
+
target="_self"
+
>
+
FR
+
</a>
+
</div>
+
<a
href="https://bsky.app/profile/did:plc:hpmpe3pzpdtxbmvhlwrevhju"
target="_blank"
rel="noopener noreferrer"
+
class="container"
>
<Icon name="pixel:bluesky" />
<span> Bluesky </span>
···
href="mailto:contact@colinozanne.fr"
target="_blank"
rel="noopener noreferrer"
+
class="container"
>
<Icon name="pixel:envelope" />
<span> Email </span>
<Icon name="pixel:external-link" class="external-link" />
</a>
-
<p>&copy; {new Date().getFullYear()} Colin Ozanne</p>
+
<p class="container">
+
&copy; {new Date().getFullYear()} Colin Ozanne
+
</p>
</footer>
</body>
</html>
···
"header main"
"footer main";
gap: 0;
-
font-family: sans-serif;
+
font-family: "Scorekard", sans-serif;
header {
grid-area: header;
···
"main"
"footer";
gap: 0;
+
height: auto;
+
min-height: 100svh;
}
}
···
font-size: 15cqi;
color: var(--clr-dark-a0);
margin: 0;
-
--aside-elem-color: var(--fuchsia-500);
-
--aside-elem-text-color: var(--fuchsia-950);
+
--container-color: var(--fuchsia-500);
+
--container-text-color: var(--fuchsia-950);
@media screen and (max-width: 768px) {
font-size: 2rem;
···
p {
margin: 0;
-
--aside-elem-color: var(--rose-500);
-
--aside-elem-text-color: var(--rose-950);
+
--container-color: var(--sky-500);
+
--container-text-color: var(--sky-950);
+
}
+
+
.lang-switcher {
+
display: flex;
+
align-items: center;
+
justify-content: center;
+
gap: 1rem;
+
+
--container-color: var(--fuchsia-100);
+
--container-text-color: var(--fuchsia-800);
+
+
a {
+
padding: 0.5rem 1rem;
+
border-radius: var(--radius);
+
background-color: var(--fuchsia-200);
+
color: inherit;
+
transition: background-color 0.2s ease-in-out;
+
+
&:hover {
+
background-color: var(--fuchsia-300);
+
}
+
+
&.active {
+
background-color: var(--fuchsia-400);
+
--container-text-color: var(--fuchsia-950);
+
}
+
}
}
a {
···
align-items: center;
justify-content: center;
gap: 0.5rem;
-
color: var(--black-500);
text-decoration: none;
transition: color 0.3s ease-in-out;
-
--aside-elem-color: var(--amber-500);
-
--aside-elem-text-color: var(--amber-950);
-
-
&:hover {
-
color: var(--clr-dark-a1);
-
}
+
--container-color: var(--amber-500);
+
--container-text-color: var(--amber-950);
svg {
--size: 1.5rem;
···
}
& > * {
-
padding: var(--spacing);
-
width: calc(100% - 2rem * var(--spacing));
-
border-radius: var(--radius);
text-align: center;
-
color: var(--aside-elem-text-color, var(--emerald-950, black));
-
background-color: var(--aside-elem-color, var(--emerald-500, red));
font-family: "Spagetty", serif;
letter-spacing: 0.01em;
font-size: 1.2rem;
···
}
main {
-
border-left: 10px solid black;
+
padding: var(--spacing);
overflow-y: scroll;
}
</style>