From f898e5d7e54c57294f14f7056531ecd2ec6e1d79 Mon Sep 17 00:00:00 2001 From: Alexander Borsuk Date: Sun, 20 Nov 2022 19:16:32 +0100 Subject: [PATCH] Serve localized donation page Signed-off-by: Alexander Borsuk --- README.md | 2 ++ functions/donate.ts | 39 +++++++++++++++++++++++++++++++++++++++ functions/tsconfig.json | 8 ++++++++ static/_routes.json | 5 +++++ 4 files changed, 54 insertions(+) create mode 100644 functions/donate.ts create mode 100644 functions/tsconfig.json create mode 100644 static/_routes.json diff --git a/README.md b/README.md index e93090d8..cd09ae44 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ This website is build with [Zola](https://www.getzola.org/) and Cloudflare Pages Use `zola serve` for a local preview or `zola build` to generate static site in the `public` folder. +To test Clouldflare Functions locally, use `npx wrangler pages dev public` after doing `zola build`. + `npm i && npm run format` will pretty-format Markdown and scss. Upgrade npm dependencies with `npm run upgrade`, make sure that you have installed `npm-check-updates` package. diff --git a/functions/donate.ts b/functions/donate.ts new file mode 100644 index 00000000..08d27314 --- /dev/null +++ b/functions/donate.ts @@ -0,0 +1,39 @@ +// Redirects users from the default en donate page to the appropriate localized version. +interface Env { + KV: KVNamespace; +} + +// TODO: Detect if donation page already has translation in resources automatically, +// without hard-coded list +const localizedLanguages = ['ru', 'it', 'tr']; + +// To parse accept-language like this: +// fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5 +// en-AU,en;q=0.8,be;q=0.6,ru;q=0.4,uk;q=0.2 +const langCodeRegex = /[a-z]{2}/g; + +// Returns user's preferred languages: ["en", "be", "ru"] +function extractLanguageList(acceptLanguage: string): string[] { + const langs = acceptLanguage.match(langCodeRegex); + return [...new Set(langs)]; // Filter duplicates. +} + +// Should be invoked only for /donate or /donate/ routes +export const onRequest: PagesFunction = async (context) => { + console.log('Donate handler hit url:' + context.request.url); + + const acceptLanguage = context.request.headers.get('accept-language'); + if (acceptLanguage) { + // Is there a localized version? + const languages = extractLanguageList(acceptLanguage); + const filtered = localizedLanguages.filter(lang => languages.includes(lang)); + if (filtered.length) { + const url = new URL(context.request.url); + console.log('Old pathname: ' + url.pathname); + url.pathname = '/' + filtered[0] + url.pathname; + return context.env.ASSETS.fetch(url); + } + } + // Return default en version. + return context.env.ASSETS.fetch(context.request.url); +} diff --git a/functions/tsconfig.json b/functions/tsconfig.json new file mode 100644 index 00000000..da95421c --- /dev/null +++ b/functions/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "lib": ["esnext"], + "types": ["@cloudflare/workers-types"] + } +} diff --git a/static/_routes.json b/static/_routes.json new file mode 100644 index 00000000..8cc07033 --- /dev/null +++ b/static/_routes.json @@ -0,0 +1,5 @@ +{ + "version": 1, + "include": ["/donate", "/donate/"], + "exclude": [] +}