Added localization support

This commit is contained in:
Filip Znachor 2024-05-30 22:17:05 +02:00
parent 6b26f7db9b
commit 6dcf41567a
10 changed files with 150 additions and 47 deletions

19
astro-i18n.config.ts Normal file
View file

@ -0,0 +1,19 @@
import { defineAstroI18nConfig } from "astro-i18n"
export default defineAstroI18nConfig({
primaryLocale: "cs",
secondaryLocales: ["en"],
fallbackLocale: "cs",
trailingSlash: "never",
run: "server",
showPrimaryLocale: false,
translationLoadingRules: [],
translationDirectory: {},
translations: {},
routes: {
"en": {
sluzby: "services",
kontakt: "contact"
}
}
})

View file

@ -15,7 +15,7 @@
"@iconify-json/tabler": "^1.1.110",
"astro": "^4.6.3",
"astro-icon": "^1.1.0",
"localtunnel": "^2.0.2",
"typescript": "^5.4.5"
"astro-i18n": "^2.2.4",
"typescript": "^5.4.5"
}
}

View file

@ -2,12 +2,12 @@
import { Icon } from 'astro-icon/components';
import NavLink from './NavLink.astro';
import "../styles/nav.css";
import { t, l } from "astro-i18n";
const nav = [
{title: "Úvod", link: "/"},
{title: "Služby", link: "/sluzby"},
// {title: "O nás", link: "/o-nas"},
{title: "Kontakt", link: "/kontakt"}
{title: "home", link: l("/")},
{title: "services", link: l("/sluzby")},
{title: "contact", link: l("/kontakt")}
];
---
@ -15,7 +15,7 @@ const nav = [
<nav>
<div class="inner">
<div class="title">
<a href="/" class="logo">
<a href={ l("/") } class="logo">
<img src="/assets/logo.webp" />
</a>
<label for="menu-toggle">
@ -25,14 +25,14 @@ const nav = [
<ul>
{ nav.map(item =>
<li>
<NavLink href={item.link}>{item.title}</NavLink>
<NavLink href={item.link}>{ t(`nav.${item.title}`) }</NavLink>
</li>
) }
<li class="right">
<a href="https://status.codespace.cz" target="_blank">Stav služeb <Icon name="tabler:external-link"></a>
<a href="https://status.codespace.cz" target="_blank">{ t("nav.status") } <Icon name="tabler:external-link"></a>
</li>
<li>
<a href="https://wiki.codespace.cz" target="_blank">Wiki <Icon name="tabler:external-link"></a>
<a href="https://wiki.codespace.cz" target="_blank">{ t("nav.wiki") } <Icon name="tabler:external-link"></a>
</li>
</ul>
</div>

View file

@ -1,14 +1,14 @@
---
import { Icon } from 'astro-icon/components';
import { t } from "astro-i18n";
type Props = Service;
interface Service {
icon: string;
name: string;
desc: string;
url?: string;
invite?: boolean;
id: string,
icon: string,
url?: string,
invite?: boolean
}
const service = Astro.props;
@ -17,15 +17,15 @@ const service = Astro.props;
<div class="service">
<div class="title">
<Icon name={ service.icon } />
<h3>{ service.name }</h3>
<h3>{ t(`services.${service.id}.title`) }</h3>
</div>
<p>{ service.desc }</p>
<p>{ t(`services.${service.id}.description`) }</p>
<div class="bottom">
{ service.url &&
{ service.url &&
<a href={ "https://" + service.url } target="_blank"><Icon name="tabler:link" /> { service.url }</a>
}
{ service.invite &&
<div class="label">na pozvání</div>
{ service.invite &&
<div class="label">{ t("services.labels.invite") }</div>
}
</div>
</div>

75
src/i18n/common/cs.json Normal file
View file

@ -0,0 +1,75 @@
{
"nav": {
"home": "Úvod",
"services": "Služby",
"contact": "Kontakt",
"status": "Stav služeb",
"wiki": "Wiki"
},
"home": {
"meta": {
"title": "CodeSpace.cz - svoboda a nezávislost v digitální době"
},
"header": {
"title": "Spojuje nás touha po <span>svobodě</span> a <span>nezávislosti</span> v digitální době.",
"description": "Provozujeme si vlastní síť a servery, abychom nemuseli spoléhat na ostatní. Poskytujeme různé služby, které respektují naše soukromí."
},
"services": {
"title": "Služby",
"description": "Přehled hlavních služeb, které provozujeme.",
"more": "Kompletní seznam služeb naleznete na <a href=\"{# link #}\">stránce služeb</a>."
}
},
"services": {
"title": "Služby",
"description": "Přehled všech služeb, které na své infrastruktuře provozujeme.",
"public": {
"title": "Veřejné služby",
"description": "Přehled všech provozovaných veřejných služeb."
},
"for_members": {
"title": "Služby pro členy",
"description": "Provozujeme také další služby, které jsou určeny především naším členům."
},
"more": "Dokážeme vám individuálně poskytnout i široké spektrum <a href=\"{# link #}\" target=\"_blank\">dalších služeb</a>.",
"labels": {
"invite": "na pozvání"
},
"piped": {
"title": "Piped",
"description": "Alternativní frontend pro YouTube, který vás nesleduje a je bez reklam."
},
"pipedmusic": {
"title": "Piped Music",
"description": "Náš open-source klient pro poslech hudby, který vaše data s nikým nesdílí."
},
"send": {
"title": "Send",
"description": "Posílejte až 10 GB souborů bezpečně a soukromě s end-to-end šifrováním."
},
"forgejo": {
"title": "Forgejo",
"description": "Jednoduchá a nenáročná nadstavba Gitu, na které vyvíjíme své projekty."
},
"vaultwarden": {
"title": "Vaultwarden",
"description": "Správce hesel s užitečnými funkcemi kompatibilní s Bitwardenem."
},
"plausible": {
"title": "Plausible",
"description": "Statistiky návštěvnosti webových stránek respektující soukromí návštěvníků."
},
"nextcloud": {
"title": "Nextcloud",
"description": "Úložiště souborů s možností synchronizace a spoustou užitečných aplikací."
},
"webhosting": {
"title": "Webhosting",
"description": "Nabízíme webhostingové služby na naší vlastní platformě."
}
},
"contact": {
"title": "Kontakt",
"description": "Způsoby, kterými nás můžete kontaktovat."
}
}

6
src/middleware/index.ts Normal file
View file

@ -0,0 +1,6 @@
import { sequence } from "astro/middleware";
import { useAstroI18n } from "astro-i18n";
const astroI18n = useAstroI18n();
export const onRequest = sequence(astroI18n);

View file

@ -2,9 +2,10 @@
import Service from '../components/Service.astro';
import Layout from '../layouts/Layout.astro';
import { public_services, invite_services } from '../scripts/services';
import { t, l } from "astro-i18n";
const meta = {
title: "CodeSpace.cz - svoboda a nezávislost v digitální době",
title: t("home.meta.title"),
use_title_suffix: false
};
---
@ -14,22 +15,22 @@ const meta = {
<div class="inner">
<div class="grid">
<div>
<h1>Spojuje nás touha po <span>svobodě</span> a <span>nezávislosti</span> v digitální době.</h1>
<p>Provozujeme si vlastní síť a servery, abychom nemuseli spoléhat na ostatní. Poskytujeme různé služby, které respektují naše soukromí.</p>
<h1 set:html={ t("home.header.title") }></h1>
<p>{ t("home.header.description") }</p>
</div>
</div>
</div>
</header>
<section>
<div class="inner">
<h2>Služby</h2>
<p>Přehled hlavních služeb, které provozujeme.</p>
<h2>{ t("home.services.title") }</h2>
<p>{ t("home.services.description") }</p>
<div class="services">
{ [...public_services, ...invite_services].slice(0, 6).map(service =>
<Service {...service} />
) }
</div>
<p>Kompletní seznam služeb naleznete na <a href="/sluzby">stránce služeb</a>.</p>
<p set:html={ t("home.services.more", {link: l("/sluzby")}) }></p>
</div>
</section>
</Layout>

View file

@ -1,16 +1,17 @@
---
import Layout from '../layouts/Layout.astro';
import { t } from "astro-i18n";
const meta = {
title: "Kontakt",
desc: "Způsoby, kterými nás můžete kontaktovat."
title: t("contact.title"),
desc: t("contact.desc")
};
---
<Layout meta={meta}>
<header>
<div class="inner">
<h1>Kontakt</h1>
<h1>{ t("contact.title") }</h1>
<p>email: <a href="mailto:hello@codespace.cz">hello@codespace.cz</a></p>
</div>
</header>

View file

@ -1,25 +1,26 @@
---
import Layout from '../layouts/Layout.astro';
import { invite_services, public_services } from '../scripts/services';
import Service from '../components/Service.astro';
import { invite_services, public_services } from '../scripts/services';
import { t } from "astro-i18n";
const meta = {
title: "Služby",
desc: "Přehled veřejných služeb, které provozujeme."
title: t("services.title"),
desc: t("services.description")
};
---
<Layout meta={meta}>
<header>
<div class="inner">
<h1>Služby</h1>
<p>Přehled všech služeb, které na své infrastruktuře provozujeme.</p>
<h1>{ t("services.title") }</h1>
<p>{ t("services.description") }</p>
</div>
</header>
<section>
<div class="inner">
<h2>Veřejné služby</h2>
<p>Přehled všech provozovaných veřejných služeb.</p>
<h2>{ t("services.public.title") }</h2>
<p>{ t("services.public.description") }</p>
<div class="services">
{ public_services.map(service =>
<Service {...service} />
@ -29,14 +30,14 @@ const meta = {
</section>
<section>
<div class="inner">
<h2>Služby pro členy</h2>
<p>Provozujeme také další služby, které jsou určeny především naším členům.</p>
<h2>{ t("services.for_members.title") }</h2>
<p>{ t("services.for_members.description") }</p>
<div class="services">
{ invite_services.map(service =>
<Service {...service} />
) }
</div>
<p>Dokážeme vám individuálně poskytnout i široké spektrum <a href="//wiki.cdsp.cz/services" target="_blank">dalších služeb</a>.</p>
<p set:html={ t("services.more", {link: "https://wiki.cdsp.cz/services"}) }></p>
</div>
</section>
</Layout>

View file

@ -1,13 +1,13 @@
export const public_services = [
{name: "Piped", icon: "tabler:brand-youtube", desc: "Alternativní frontend pro YouTube, který vás nesleduje a je bez reklam.", url: "yt.cdsp.cz"},
{name: "Piped Music", icon: "tabler:headphones", desc: "Náš open-source klient pro poslech hudby, který vaše data s nikým nesdílí.", url: "pm.cdsp.cz"},
{name: "Send", icon: "tabler:cloud-upload", desc: "Posílejte až 10 GB souborů bezpečně a soukromě s end-to-end šifrováním.", url: "send.cdsp.cz"}
{id: "piped", icon: "tabler:brand-youtube", url: "yt.cdsp.cz"},
{id: "pipedmusic", icon: "tabler:headphones", url: "pm.cdsp.cz"},
{id: "send", icon: "tabler:cloud-upload", url: "send.cdsp.cz"}
];
export const invite_services = [
{name: "Forgejo", icon: "tabler:brand-git", desc: "Jednoduchá a nenáročná nadstavba Gitu, na které vyvíjíme své projekty.", url: "git.cdsp.cz", invite: true},
{name: "Vaultwarden", icon: "tabler:key", desc: "Správce hesel s užitečnými funkcemi kompatibilní s Bitwardenem.", url: "vault.cdsp.cz", invite: true},
{name: "Plausible", icon: "tabler:chart-pie", desc: "Statistiky návštěvnosti webových stránek respektující soukromí návštěvníků.", url: "plausible.cdsp.cz", invite: true},
{name: "Nextcloud", icon: "tabler:brand-nextcloud", desc: "Úložiště souborů s možností synchronizace a spoustou užitečných aplikací.", invite: true},
{name: "Webhosting", icon: "tabler:world", desc: "Nabízíme webhostingové služby na naší vlastní platformě.", url: "oohost.cz", invite: true}
{id: "forgejo", icon: "tabler:brand-git", url: "git.cdsp.cz", invite: true},
{id: "vaultwarden", icon: "tabler:key", url: "vault.cdsp.cz", invite: true},
{id: "plausible", icon: "tabler:chart-pie", url: "plausible.cdsp.cz", invite: true},
{id: "nextcloud", icon: "tabler:brand-nextcloud", invite: true},
{id: "webhosting", icon: "tabler:world", url: "oohost.cz", invite: true}
];