Add translations
This commit is contained in:
parent
5792decc8f
commit
a8903e7279
10 changed files with 102 additions and 12 deletions
66
src/i18n.ts
66
src/i18n.ts
|
@ -1,3 +1,65 @@
|
|||
export function t(key: string) {
|
||||
return key;
|
||||
import { DEFAULT_LANG } from "./config";
|
||||
import type { Lang } from "./lang";
|
||||
|
||||
type AnyString = string & {};
|
||||
|
||||
// Reference
|
||||
const en = {
|
||||
website_name: "Let's stop dirty money",
|
||||
website_description: undefined,
|
||||
switch_country: "Switch country",
|
||||
"form.first_name": "First name",
|
||||
"form.last_name": "Last name",
|
||||
"form.variant": "I'm most concerned that",
|
||||
"form.variant.1": "EPH destroys global climate",
|
||||
"form.variant.2": "EPH fuels energy crisis",
|
||||
"form.variant.3": "EPH undermines democracy",
|
||||
"form.gender": undefined,
|
||||
"form.gender.f": undefined,
|
||||
"form.gender.m": undefined,
|
||||
"form.branch": "I'm client of",
|
||||
"form.letter": "Letter body",
|
||||
"form.email": "E-mail",
|
||||
"form.phone": "Phone number",
|
||||
"form.send": "Send",
|
||||
"confirm_email.title": "Confirm your e-mail",
|
||||
"confirm_email.body": "Click the link below to verify your e-mail address.",
|
||||
"confirm_email.link": "Confirm",
|
||||
} as const;
|
||||
|
||||
type TranslationKey = keyof typeof en;
|
||||
type Translation = Partial<Record<TranslationKey | AnyString, string | undefined>>;
|
||||
|
||||
const cs: Translation = {
|
||||
website_name: "Zastavme špinavé prachy",
|
||||
switch_country: "Změnit zemi",
|
||||
"form.first_name": "Jméno",
|
||||
"form.last_name": "Příjmení",
|
||||
"form.variant": "Nejvíc mi vadí, že",
|
||||
"form.variant.1": "EPH ničí klima",
|
||||
"form.variant.2": "EPH způsobuje energetickou krizi",
|
||||
"form.variant.3": "EPH ohrožuje demokracii",
|
||||
"form.gender": "Preferuju být oslován/a v",
|
||||
"form.gender.f": "ženském rodě",
|
||||
"form.gender.m": "mužském rodě",
|
||||
"form.branch": "Jsem klient/ka pobočky",
|
||||
"form.letter": "Text dopisu",
|
||||
"form.email": "E-mail",
|
||||
"form.phone": "Telefonní číslo",
|
||||
"form.send": "Odeslat",
|
||||
"confirm_email.title": "Potvrď svůj e-mail",
|
||||
"confirm_email.body": "Kliknutím na následující odkaz potvrdíš svou e-mailovou adresu.",
|
||||
"confirm_email.link": "Potvrdit e-mail",
|
||||
};
|
||||
|
||||
const de: Translation = {};
|
||||
|
||||
const translations: Record<Lang, Translation> = { en, cs, de };
|
||||
|
||||
export type TranslateFn = (key: TranslationKey | AnyString) => string;
|
||||
|
||||
export function makeT(lang: Lang = DEFAULT_LANG): TranslateFn {
|
||||
return function t(key) {
|
||||
return translations[lang]?.[key] ?? key;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@ import { LANGUAGES } from "./config.ts";
|
|||
|
||||
export type Lang = (typeof LANGUAGES)[number];
|
||||
|
||||
export function isLang(str: string): str is Lang {
|
||||
return (LANGUAGES as ReadonlyArray<string>).includes(str);
|
||||
export function isLang(str: string | undefined): str is Lang {
|
||||
return !!str && (LANGUAGES as ReadonlyArray<string>).includes(str);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
---
|
||||
import { t } from "../i18n";
|
||||
import { DEFAULT_LANG } from "../config";
|
||||
import { makeT } from "../i18n";
|
||||
import type { Lang } from "../lang";
|
||||
|
||||
interface Props {
|
||||
lang?: Lang;
|
||||
}
|
||||
|
||||
const { lang = DEFAULT_LANG } = Astro.props;
|
||||
const t = makeT(lang);
|
||||
---
|
||||
|
||||
<html>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import { t } from "../i18n";
|
||||
import { makeT } from "../i18n";
|
||||
import Button from "../ui/Button.astro";
|
||||
import Dialog from "../ui/Dialog.astro";
|
||||
import Checkbox from "../ui/Checkbox.astro";
|
||||
|
@ -14,6 +14,7 @@ interface Props {
|
|||
}
|
||||
|
||||
const { lang, options = {} } = Astro.props;
|
||||
const t = makeT(lang);
|
||||
const result = letterOptionsSchema.safeParse(options);
|
||||
---
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import Field from "../ui/Field.astro";
|
||||
import Radio from "../ui/Radio.astro";
|
||||
import RadioGroup from "../ui/RadioGroup.astro";
|
||||
import { t } from "../i18n";
|
||||
import { makeT } from "../i18n";
|
||||
import Label from "../ui/Label.astro";
|
||||
import Select from "../ui/Select.astro";
|
||||
import type { Lang } from "../lang";
|
||||
|
@ -12,6 +12,7 @@ interface Props {
|
|||
}
|
||||
|
||||
const { lang } = Astro.props;
|
||||
const t = makeT(lang);
|
||||
|
||||
interface Branch {
|
||||
id: number;
|
||||
|
|
|
@ -27,7 +27,7 @@ const responseSchema = z.object({
|
|||
data: z.record(z.any()),
|
||||
});
|
||||
|
||||
function convertObjectKeys<T>(
|
||||
function convertObjectKeys(
|
||||
obj: Record<string, any>,
|
||||
fn: (key: string) => string
|
||||
): Record<string, any> {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import html from "html-template-tag";
|
||||
import { t } from "../i18n";
|
||||
import { makeT } from "../i18n";
|
||||
import type { Lang } from "../lang";
|
||||
|
||||
interface Params {
|
||||
lang: string;
|
||||
lang: Lang;
|
||||
href: string;
|
||||
}
|
||||
|
||||
export default function renderMail({ lang, href }: Params) {
|
||||
const t = makeT(lang);
|
||||
const htmlBody = html`<!DOCTYPE html>
|
||||
<html lang="${lang}">
|
||||
<head>
|
||||
|
|
14
src/middleware.ts
Normal file
14
src/middleware.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import type { MiddlewareHandler } from "astro";
|
||||
import { isLang } from "./lang";
|
||||
|
||||
export const onRequest: MiddlewareHandler = ({ params }, next) => {
|
||||
// Return 404 on unknown languages
|
||||
// On statically generated routes, this behavior is automatically handled by getStaticPaths.
|
||||
if (params.lang && !isLang(params.lang)) {
|
||||
return new Response(null, {
|
||||
status: 404,
|
||||
statusText: "Not found",
|
||||
});
|
||||
}
|
||||
return next();
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import { t } from "../../i18n";
|
||||
import { makeT } from "../../i18n";
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
import LetterBodyForm from "../../letter/LetterBodyForm.astro";
|
||||
import LetterOptionsForm from "../../letter/LetterOptionsForm.astro";
|
||||
|
@ -7,6 +7,7 @@ import LetterOptionsForm from "../../letter/LetterOptionsForm.astro";
|
|||
export { getStaticPaths } from "../../static-paths";
|
||||
|
||||
const { lang } = Astro.params;
|
||||
const t = makeT(lang);
|
||||
---
|
||||
|
||||
<Layout>
|
||||
|
|
|
@ -12,7 +12,7 @@ export async function GET({ params: { lang } }: APIContext<never, Params>) {
|
|||
const { plainBody } = renderMail({ lang, href: "" });
|
||||
return new Response(plainBody, {
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
"Content-Type": "text/plain;charset=utf-8",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
Reference in a new issue