diff --git a/config/scripts.yaml b/config/scripts.yaml
index d26cbd7e176..4956aff14c0 100644
--- a/config/scripts.yaml
+++ b/config/scripts.yaml
@@ -61,7 +61,6 @@ backend:
rmdb: 'node ./scripts/rmdb.mjs'
test: 'npx mocha --require mocha-steps tests/index.mjs'
vbuild: *vbuild
- prebuild: &sitePrebuild 'node --conditions=internal --experimental-json-modules ./prebuild.mjs'
dev:
build: &nextBuild 'next build'
@@ -71,7 +70,7 @@ dev:
develop: *nextDev
i18n: "SITE=dev node --conditions=internal ../shared/prebuild/i18n-only.mjs"
lint: &nextLint 'next lint'
- prebuild: *sitePrebuild
+ prebuild: &sitePrebuild 'node --conditions=internal --experimental-json-modules ./prebuild.mjs'
serve: "pm2 start npm --name 'dev' -- run start"
start: &nextStart 'yarn prebuild && yarn dev'
diff --git a/markdown/org/docs/faq/newsletter/en.md b/markdown/org/docs/faq/newsletter/en.md
new file mode 100644
index 00000000000..b7633e62566
--- /dev/null
+++ b/markdown/org/docs/faq/newsletter/en.md
@@ -0,0 +1,5 @@
+---
+title: Newsletter
+---
+
+
diff --git a/markdown/org/docs/faq/newsletter/why-subscribe-multiple-clicks/en.md b/markdown/org/docs/faq/newsletter/why-subscribe-multiple-clicks/en.md
new file mode 100644
index 00000000000..1c4e39e4f26
--- /dev/null
+++ b/markdown/org/docs/faq/newsletter/why-subscribe-multiple-clicks/en.md
@@ -0,0 +1,66 @@
+---
+title: Why do I have to click again to confirm I want to subscribe after I already clicked the confirmation link you sent me?
+---
+
+There are two aspects that cause signing up for our newsletter to require multiple clicks:
+
+- [People should only be able to sign up themselves](#people-should-only-be-able-to-sign-up-themselves)
+- [GET requests should not make changes](#get-requests-should-not-make-changes)
+
+## People should only be able to sign up themselves
+
+This one is pretty easy to understand. One should not be able
+to subscribe somebody else's email address to the FreeSewing newsletter.
+
+This is why, after indicating you want to sign up, we sent you a confirmation
+email to the email address you provided.
+If you receive this email, it confirms not only that the email address
+is working, but also that you have access to it.
+
+In other words, only after you click the link in the confirmation email can we know for
+cerntain that:
+
+- The email address is valid
+- The owner of the email address wants to subscribe
+
+That's where it would be over. Except for one technical detail that's also important:
+
+## GET requests should not make changes
+
+This is more technical and harder to understand
+
+Another reason is that while we could make it so that clicking the link in your
+email would immeadiatly subcribe you, it would be in violation of internet standards.
+Specifically, the __HTTP__ protocol's __GET method__ definition which states that:
+
+
+
+
GET requests should only retrieve data and should have no other effect.
+
+[wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages](https://en.wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages)
+
+
+A _GET request_ is what happens when you follow a link. Merely following a link
+should not make any changes (like subscribing you to a newsletter).
+
+For example, when you receive an email, your email client
+may _preload_ the links in it in the background. So that they are quicker to
+load should you click on them.
+
+Obviously, this preloading should not confirm your subscription. Which is why
+you need to click a button to confirm. Because that will trigger a __POST request__
+and those can make changes.
+
+
+
+##### This does not apply to users subscribing through their account
+
+None of this applies to users who subscribe to our newsletter by enabling the
+option in our account. In this case, we do not need to go through the email
+validation process, since we already did that when you signed up.
+
+For users, subscribing (and unsubscribing) is instant (If you are curious,
+we use an idempotent __PUT request__ under the hood).
+
+
+
diff --git a/markdown/org/docs/faq/newsletter/why-unsubscribe-multiple-clicks/en.md b/markdown/org/docs/faq/newsletter/why-unsubscribe-multiple-clicks/en.md
new file mode 100644
index 00000000000..1c4e39e4f26
--- /dev/null
+++ b/markdown/org/docs/faq/newsletter/why-unsubscribe-multiple-clicks/en.md
@@ -0,0 +1,66 @@
+---
+title: Why do I have to click again to confirm I want to subscribe after I already clicked the confirmation link you sent me?
+---
+
+There are two aspects that cause signing up for our newsletter to require multiple clicks:
+
+- [People should only be able to sign up themselves](#people-should-only-be-able-to-sign-up-themselves)
+- [GET requests should not make changes](#get-requests-should-not-make-changes)
+
+## People should only be able to sign up themselves
+
+This one is pretty easy to understand. One should not be able
+to subscribe somebody else's email address to the FreeSewing newsletter.
+
+This is why, after indicating you want to sign up, we sent you a confirmation
+email to the email address you provided.
+If you receive this email, it confirms not only that the email address
+is working, but also that you have access to it.
+
+In other words, only after you click the link in the confirmation email can we know for
+cerntain that:
+
+- The email address is valid
+- The owner of the email address wants to subscribe
+
+That's where it would be over. Except for one technical detail that's also important:
+
+## GET requests should not make changes
+
+This is more technical and harder to understand
+
+Another reason is that while we could make it so that clicking the link in your
+email would immeadiatly subcribe you, it would be in violation of internet standards.
+Specifically, the __HTTP__ protocol's __GET method__ definition which states that:
+
+
+
+
GET requests should only retrieve data and should have no other effect.
+
+[wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages](https://en.wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages)
+
+
+A _GET request_ is what happens when you follow a link. Merely following a link
+should not make any changes (like subscribing you to a newsletter).
+
+For example, when you receive an email, your email client
+may _preload_ the links in it in the background. So that they are quicker to
+load should you click on them.
+
+Obviously, this preloading should not confirm your subscription. Which is why
+you need to click a button to confirm. Because that will trigger a __POST request__
+and those can make changes.
+
+
+
+##### This does not apply to users subscribing through their account
+
+None of this applies to users who subscribe to our newsletter by enabling the
+option in our account. In this case, we do not need to go through the email
+validation process, since we already did that when you signed up.
+
+For users, subscribing (and unsubscribing) is instant (If you are curious,
+we use an idempotent __PUT request__ under the hood).
+
+
+
diff --git a/sites/backend/package.json b/sites/backend/package.json
index 42256a1c778..e516d8cec2b 100644
--- a/sites/backend/package.json
+++ b/sites/backend/package.json
@@ -24,9 +24,7 @@
"rmdb": "node ./scripts/rmdb.mjs",
"test": "npx mocha --require mocha-steps tests/index.mjs",
"vbuild": "VERBOSE=1 node build.mjs",
- "prebuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs",
- "wbuild": "node build.mjs",
- "prewbuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs"
+ "wbuild": "node build.mjs"
},
"peerDependencies": {},
"dependencies": {
diff --git a/sites/backend/prebuild.mjs b/sites/backend/prebuild.mjs
deleted file mode 100644
index bddd11c3d97..00000000000
--- a/sites/backend/prebuild.mjs
+++ /dev/null
@@ -1,14 +0,0 @@
-import { prebuildRunner } from '../shared/prebuild/runner.mjs'
-
-/*
- * This handles the prebuild step for the FreeSewing backend
- * It runs via an NPM run script, so in a pure NodeJS context
- *
- * See `sites/org/prebuild.mjs` for an example with inline comments
- */
-prebuildRunner({
- site: 'backend',
- prebuild: {
- i18n: true,
- },
-})
diff --git a/sites/backend/prisma/schema.prisma b/sites/backend/prisma/schema.prisma
index 0881c6ebb5f..957bf9f39c6 100644
--- a/sites/backend/prisma/schema.prisma
+++ b/sites/backend/prisma/schema.prisma
@@ -30,10 +30,11 @@ model Confirmation {
model Subscriber {
id String @id @default(uuid())
+ active Boolean @default(false)
createdAt DateTime @default(now())
- data String
ehash String @unique
email String
+ language String @default("en")
updatedAt DateTime @updatedAt
}
diff --git a/sites/backend/src/config.mjs b/sites/backend/src/config.mjs
index 210d02b4bc5..7a9c7f692ac 100644
--- a/sites/backend/src/config.mjs
+++ b/sites/backend/src/config.mjs
@@ -35,6 +35,8 @@ const baseConfig = {
env: process.env.NODE_ENV || 'development',
// Maintainer contact
maintainer: 'joost@freesewing.org',
+ // Backend API base URL
+ api: process.env.BACKEND_API_URL || 'https://backend3.freesewing.org',
// Feature flags
use: {
github: envToBool(process.env.BACKEND_ENABLE_GITHUB),
@@ -44,12 +46,12 @@ const baseConfig = {
},
sanity: envToBool(process.env.BACKEND_ENABLE_SANITY),
ses: envToBool(process.env.BACKEND_ENABLE_AWS_SES),
- stripe: envToBool(process.env.BACKEND_ENABLE_PAYMENTS),
tests: {
base: envToBool(process.env.BACKEND_ENABLE_TESTS),
email: envToBool(process.env.BACKEND_ENABLE_TESTS_EMAIL),
sanity: envToBool(process.env.BACKEND_ENABLE_TESTS_SANITY),
},
+ import: envToBool(process.env.BACKEND_ENABLE_IMPORT),
},
// Config
api,
@@ -86,7 +88,7 @@ const baseConfig = {
audience: process.env.BACKEND_JWT_ISSUER || 'freesewing.org',
expiresIn: process.env.BACKEND_JWT_EXPIRY || '7d',
},
- languages: ['en', 'de', 'es', 'fr', 'nl'],
+ languages: ['en', 'de', 'es', 'fr', 'nl', 'uk'],
translations: ['de', 'es', 'fr', 'nl', 'uk'],
measies: measurements,
mfa: {
@@ -145,7 +147,7 @@ if (baseConfig.use.github)
if (baseConfig.use.sanity)
baseConfig.sanity = {
project: process.env.SANITY_PROJECT,
- dataset: process.env.SANITY_DATASET || 'production',
+ dataset: process.env.SANITY_DATASET || 'site-content',
token: process.env.SANITY_TOKEN || 'fixmeSetSanityToken',
version: process.env.SANITY_VERSION || 'v2022-10-31',
api: `https://${process.env.SANITY_PROJECT || 'missing-project-id'}.api.sanity.io/${
@@ -153,14 +155,6 @@ if (baseConfig.use.sanity)
}`,
}
-// Stripe config
-if (baseConfig.use.stripe)
- baseConfig.stripe = {
- keys: {
- createIntent: process.env.BACKEND_STRIPE_CREATE_INTENT_KEY || false,
- },
- }
-
// AWS SES config (for sending out emails)
if (baseConfig.use.ses)
baseConfig.aws = {
@@ -260,10 +254,6 @@ if (envToBool(process.env.BACKEND_ENABLE_OAUTH_GOOGLE)) {
vars.BACKEND_OAUTH_GOOGLE_CLIENT_ID = 'required'
vars.BACKEND_OAUTH_GOOGLE_CLIENT_SECRET = 'requiredSecret'
}
-// Vars for Stripe integration
-if (envToBool(process.env.BACKEND_ENABLE_PAYMENTS)) {
- vars.BACKEND_STRIPE_CREATE_INTENT_KEY = 'requiredSecret'
-}
// Vars for (unit) tests
if (envToBool(process.env.BACKEND_ENABLE_TESTS)) {
@@ -339,11 +329,6 @@ export function verifyConfig(silent = false) {
config.jwt.secretOrKey.slice(0, 4) + '**redacted**' + config.jwt.secretOrKey.slice(-4),
},
}
- if (config.stripe)
- dump.stripe = {
- ...config.stripe.keys,
- //token: config.sanity.token.slice(0, 4) + '**redacted**' + config.sanity.token.slice(-4),
- }
if (config.sanity)
dump.sanity = {
...config.sanity,
diff --git a/sites/backend/src/controllers/imports.mjs b/sites/backend/src/controllers/imports.mjs
new file mode 100644
index 00000000000..958e2cdea4b
--- /dev/null
+++ b/sites/backend/src/controllers/imports.mjs
@@ -0,0 +1,18 @@
+import { ImportModel } from '../models/import.mjs'
+
+export function ImportsController() {}
+
+/*
+ * Imports newsletters subscribers in v2 format
+ */
+ImportsController.prototype.subscribers = async (req, res, tools) => {
+ /*
+ * This is a special route that uses hard-coded credentials
+ */
+ console.log(req.body)
+
+ const Import = new ImportModel(tools)
+ //await Flow.sendTranslatorInvite(req)
+
+ return Import.sendResponse(res)
+}
diff --git a/sites/backend/src/controllers/payments.mjs b/sites/backend/src/controllers/payments.mjs
deleted file mode 100644
index 08e5543de9f..00000000000
--- a/sites/backend/src/controllers/payments.mjs
+++ /dev/null
@@ -1,34 +0,0 @@
-export function PaymentsController() {}
-
-/*
- * Create payment intent
- *
- * This is the endpoint that handles creation of a Stripe payment intent
- * See: https://freesewing.dev/reference/backend/api/apikey
- */
-PaymentsController.prototype.createIntent = async (req, res, tools) => {
- if (!req.body.amount) return this.setResponse(400, 'amountMissing')
- if (!req.body.currency) return this.setResponse(400, 'currencyMissing')
-
- const body = new URLSearchParams()
- body.append('amount', req.body.amount)
- body.append('currency', req.body.currency)
-
- // Call Stripe API with fetch to create the payment inent
- const result = await fetch('https://api.stripe.com/v1/payment_intents', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
- authorization: `Bearer ${tools.config.stripe.keys.createIntent}`,
- },
- body,
- })
- // Convert response to JSON
- const json = await result.json()
-
- // Return status code 201 (created) and clientSecret
- return res.status(201).send({
- result: 'success',
- clientSecret: json.client_secret,
- })
-}
diff --git a/sites/backend/src/controllers/subscribers.mjs b/sites/backend/src/controllers/subscribers.mjs
new file mode 100644
index 00000000000..3fe58934314
--- /dev/null
+++ b/sites/backend/src/controllers/subscribers.mjs
@@ -0,0 +1,68 @@
+//import fs from 'fs'
+//import path from 'path'
+import { SubscriberModel } from '../models/subscriber.mjs'
+
+/*
+ * Load pages for subscribe and unsubscribe confirmation
+ * Some people might find this extra step annoying,
+ * but GET requests should not make changes.
+ */
+//const index = fs.readFileSync(path.resolve('.', 'src', 'landing', 'index.html'))
+//app.get('/', async (req, res) => res.set('Content-Type', 'text/html').status(200).send(index))
+
+export function SubscribersController() {}
+
+/*
+ * Subscribe to the newsletter (sends confirmation email)
+ * See: https://freesewing.dev/reference/backend/api
+ */
+SubscribersController.prototype.subscribe = async (req, res, tools) => {
+ const Subscriber = new SubscriberModel(tools)
+ await Subscriber.guardedCreate(req)
+
+ return Subscriber.sendResponse(res)
+}
+
+/*
+ * Subscribe confirmation
+ * See: https://freesewing.dev/reference/backend/api
+ */
+SubscribersController.prototype.subscribeConfirm = async (req, res, tools) => {
+ const Subscriber = new SubscriberModel(tools)
+ await Subscriber.subscribeConfirm(req)
+
+ return Subscriber.sendResponse(res)
+}
+
+/*
+ * Unsubscribe confirmation
+ * See: https://freesewing.dev/reference/backend/api
+ */
+SubscribersController.prototype.unsubscribeConfirm = async (req, res, tools) => {
+ const Subscriber = new SubscriberModel(tools)
+ await Subscriber.unsubscribeConfirm(req)
+
+ return Subscriber.sendResponse(res)
+}
+
+/*
+ * Confirm newsletter subscription
+ * See: https://freesewing.dev/reference/backend/api
+ */
+SubscribersController.prototype.confirm = async (req, res, tools) => {
+ const Subscriber = new SubscriberModel(tools)
+ await Subscriber.confirm(req)
+
+ return Subscriber.sendResponse(res)
+}
+
+/*
+ * Unsubscribe from the newsletter
+ * See: https://freesewing.dev/reference/backend/api
+ */
+SubscribersController.unsubscribe = async (req, res, tools) => {
+ const Subscriber = new SubscriberModel(tools)
+ await Subscriber.unsubscribe(req)
+
+ return Subscriber.sendResponse(res)
+}
diff --git a/sites/backend/src/html/catch-all.mjs b/sites/backend/src/html/catch-all.mjs
new file mode 100644
index 00000000000..36763defaf8
--- /dev/null
+++ b/sites/backend/src/html/catch-all.mjs
@@ -0,0 +1,18 @@
+import { wrapper } from './shared.mjs'
+
+export const html = wrapper({
+ content: `
+
👋
+
This is the FreeSewing backend
+
+ For info about FreeSewing, try freesewing.org instead.
+
diff --git a/sites/backend/src/templates/email/signinlink/de.json b/sites/backend/src/templates/email/signinlink/de.json
new file mode 100644
index 00000000000..ab305e42e19
--- /dev/null
+++ b/sites/backend/src/templates/email/signinlink/de.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Dein Anmeldelink für FreeSewing.org",
+ "heading": "Ein geheimer Zugangslink, nur für dich",
+ "lead": "Um dich bei FreeSewing.org anzumelden, klicke auf das große schwarze Rechteck unten:",
+ "text-lead": "Um dich bei FreeSewing.org anzumelden, klicke auf den Link unten:",
+ "button": "Anmelden",
+ "closing": "Gib diese E-Mail nicht weiter, sie ist wirklich nur für dich."
+}
diff --git a/sites/backend/src/templates/email/signinlink/de.yaml b/sites/backend/src/templates/email/signinlink/de.yaml
deleted file mode 100644
index 3162e902551..00000000000
--- a/sites/backend/src/templates/email/signinlink/de.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Dein Anmeldelink für FreeSewing.org"
-heading: Ein geheimer Zugangslink, nur für dich
-lead: 'Um dich bei FreeSewing.org anzumelden, klicke auf das große schwarze Rechteck unten:'
-text-lead: 'Um dich bei FreeSewing.org anzumelden, klicke auf den Link unten:'
-button: Anmelden
-closing: Gib diese E-Mail nicht weiter, sie ist wirklich nur für dich.
diff --git a/sites/backend/src/templates/email/signinlink/en.json b/sites/backend/src/templates/email/signinlink/en.json
new file mode 100644
index 00000000000..691ba48f36c
--- /dev/null
+++ b/sites/backend/src/templates/email/signinlink/en.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Your sign-in link for FreeSewing.org",
+ "heading": "A secret access link, just for you",
+ "lead": "To sign in to FreeSewing.org, click the big black rectangle below:",
+ "text-lead": "To sign in to FreeSewing.org, click the link below:",
+ "button": "Sign in",
+ "closing": "Do not share this email, it really is just for you."
+}
diff --git a/sites/backend/src/templates/email/signinlink/en.yaml b/sites/backend/src/templates/email/signinlink/en.yaml
deleted file mode 100644
index bd327ad18ae..00000000000
--- a/sites/backend/src/templates/email/signinlink/en.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Your sign-in link for FreeSewing.org"
-heading: A secret access link, just for you
-lead: 'To sign in to FreeSewing.org, click the big black rectangle below:'
-text-lead: 'To sign in to FreeSewing.org, click the link below:'
-button: Sign in
-closing: Do not share this email, it really is just for you.
diff --git a/sites/backend/src/templates/email/signinlink/es.json b/sites/backend/src/templates/email/signinlink/es.json
new file mode 100644
index 00000000000..130bda05ada
--- /dev/null
+++ b/sites/backend/src/templates/email/signinlink/es.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Tu enlace de acceso a FreeSewing.org",
+ "heading": "Un enlace de acceso secreto, sólo para ti",
+ "lead": "Para iniciar sesión en FreeSewing.org, haz clic en el rectángulo negro grande de abajo:",
+ "text-lead": "Para iniciar sesión en FreeSewing.org, haz clic en el enlace siguiente:",
+ "button": "Inicia sesión",
+ "closing": "No compartas este correo electrónico, es realmente sólo para ti."
+}
diff --git a/sites/backend/src/templates/email/signinlink/es.yaml b/sites/backend/src/templates/email/signinlink/es.yaml
deleted file mode 100644
index 3c371f06814..00000000000
--- a/sites/backend/src/templates/email/signinlink/es.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Tu enlace de acceso a FreeSewing.org"
-heading: Un enlace de acceso secreto, sólo para ti
-lead: 'Para iniciar sesión en FreeSewing.org, haz clic en el rectángulo negro grande de abajo:'
-text-lead: 'Para iniciar sesión en FreeSewing.org, haz clic en el enlace siguiente:'
-button: Inicia sesión
-closing: No compartas este correo electrónico, es realmente sólo para ti.
diff --git a/sites/backend/src/templates/email/signinlink/fr.json b/sites/backend/src/templates/email/signinlink/fr.json
new file mode 100644
index 00000000000..185ba9f45e1
--- /dev/null
+++ b/sites/backend/src/templates/email/signinlink/fr.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Ton lien de connexion à FreeSewing.org",
+ "heading": "Un lien d'accès secret, juste pour toi",
+ "lead": "Pour te connecter à FreeSewing.org, clique sur le grand rectangle noir ci-dessous :",
+ "text-lead": "Pour te connecter à FreeSewing.org, clique sur le lien ci-dessous :",
+ "button": "Connexion",
+ "closing": "Ne partage pas cet email, il est vraiment juste pour toi."
+}
diff --git a/sites/backend/src/templates/email/signinlink/fr.yaml b/sites/backend/src/templates/email/signinlink/fr.yaml
deleted file mode 100644
index 3e715ffe20e..00000000000
--- a/sites/backend/src/templates/email/signinlink/fr.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Ton lien de connexion à FreeSewing.org"
-heading: Un lien d'accès secret, juste pour toi
-lead: 'Pour te connecter à FreeSewing.org, clique sur le grand rectangle noir ci-dessous :'
-text-lead: 'Pour te connecter à FreeSewing.org, clique sur le lien ci-dessous :'
-button: Connexion
-closing: Ne partage pas cet email, il est vraiment juste pour toi.
diff --git a/sites/backend/src/templates/email/signinlink/index.mjs b/sites/backend/src/templates/email/signinlink/index.mjs
index 961a2cdd685..9d9ce30e81c 100644
--- a/sites/backend/src/templates/email/signinlink/index.mjs
+++ b/sites/backend/src/templates/email/signinlink/index.mjs
@@ -1,10 +1,11 @@
import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs'
// Translations
-import en from '../../../../public/locales/en/signinlink.json' assert { type: 'json' }
-import de from '../../../../public/locales/de/signinlink.json' assert { type: 'json' }
-import es from '../../../../public/locales/es/signinlink.json' assert { type: 'json' }
-import fr from '../../../../public/locales/fr/signinlink.json' assert { type: 'json' }
-import nl from '../../../../public/locales/nl/signinlink.json' assert { type: 'json' }
+import en from './en.json' assert { type: 'json' }
+import de from './de.json' assert { type: 'json' }
+import es from './es.json' assert { type: 'json' }
+import fr from './fr.json' assert { type: 'json' }
+import nl from './nl.json' assert { type: 'json' }
+import uk from './uk.json' assert { type: 'json' }
export const signinlink = {
html: wrap.html(`
@@ -29,4 +30,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}}
`),
}
-export const translations = { en, de, es, fr, nl }
+export const translations = { en, de, es, fr, nl, uk }
diff --git a/sites/backend/src/templates/email/signinlink/nl.json b/sites/backend/src/templates/email/signinlink/nl.json
new file mode 100644
index 00000000000..81b37ae1c6c
--- /dev/null
+++ b/sites/backend/src/templates/email/signinlink/nl.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Je aanmeldlink voor FreeSewing.org",
+ "heading": "Een geheime toegangslink, speciaal voor jou",
+ "lead": "Klik op de grote zwarte rechthoek hieronder om je aan te melden bij FreeSewing.org:",
+ "text-lead": "Klik op de onderstaande link om je aan te melden bij FreeSewing.org:",
+ "button": "Aanmelden",
+ "closing": "Deel deze e-mail niet, hij is echt alleen voor jou."
+}
diff --git a/sites/backend/src/templates/email/signinlink/nl.yaml b/sites/backend/src/templates/email/signinlink/nl.yaml
deleted file mode 100644
index 3c833df625c..00000000000
--- a/sites/backend/src/templates/email/signinlink/nl.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Je aanmeldlink voor FreeSewing.org"
-heading: Een geheime toegangslink, speciaal voor jou
-lead: 'Klik op de grote zwarte rechthoek hieronder om je aan te melden bij FreeSewing.org:'
-text-lead: 'Klik op de onderstaande link om je aan te melden bij FreeSewing.org:'
-button: Aanmelden
-closing: Deel deze e-mail niet, hij is echt alleen voor jou.
diff --git a/sites/backend/src/templates/email/signinlink/uk.json b/sites/backend/src/templates/email/signinlink/uk.json
new file mode 100644
index 00000000000..65d2d1751ec
--- /dev/null
+++ b/sites/backend/src/templates/email/signinlink/uk.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Ваше посилання для входу на FreeSewing.org",
+ "heading": "Секретне посилання доступу, тільки для вас",
+ "lead": "Щоб увійти на FreeSewing.org, натисніть великий чорний прямокутник нижче:",
+ "text-lead": "Щоб увійти на FreeSewing.org, натисніть на посилання нижче:",
+ "button": "Вхід",
+ "closing": "Не діліться цим листом, він дійсно тільки для вас."
+}
diff --git a/sites/backend/src/templates/email/signinlink/uk.yaml b/sites/backend/src/templates/email/signinlink/uk.yaml
deleted file mode 100644
index 1f5ccfb3479..00000000000
--- a/sites/backend/src/templates/email/signinlink/uk.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Ваше посилання для входу на FreeSewing.org"
-heading: Секретне посилання доступу, тільки для вас
-lead: 'Щоб увійти на FreeSewing.org, натисніть великий чорний прямокутник нижче:'
-text-lead: 'Щоб увійти на FreeSewing.org, натисніть на посилання нижче:'
-button: Вхід
-closing: Не діліться цим листом, він дійсно тільки для вас.
diff --git a/sites/backend/src/templates/email/signup-aea/de.json b/sites/backend/src/templates/email/signup-aea/de.json
new file mode 100644
index 00000000000..1a5c18f702a
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aea/de.json
@@ -0,0 +1,9 @@
+{
+ "subject": "[FreeSewing] Du musst dich nicht registrieren, du bist schon an Bord",
+ "heading": "Willkommen zurück bei FreeSewing",
+ "preLead": "Jemand (du?) hat versucht, sich mit dieser E-Mail-Adresse zu registrieren. Aber wir haben bereits ein aktives Konto, das mit dieser E-Mail-Adresse verknüpft ist.",
+ "lead": "Um dich in dein Konto einzuloggen, klicke auf den großen schwarzen Button unten:",
+ "text-lead": "Um dich in dein Konto einzuloggen, klicke auf den Link unten:",
+ "button": "Anmelden",
+ "closing": "Mehr muss nicht getan werden."
+}
diff --git a/sites/backend/src/templates/email/signup-aea/de.yaml b/sites/backend/src/templates/email/signup-aea/de.yaml
deleted file mode 100644
index 46f73b2db1c..00000000000
--- a/sites/backend/src/templates/email/signup-aea/de.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-subject: "[FreeSewing] Du musst dich nicht registrieren, du bist schon an Bord"
-heading: Willkommen zurück bei FreeSewing
-preLead: 'Jemand (du?) hat versucht, sich mit dieser E-Mail-Adresse zu registrieren. Aber wir haben bereits ein aktives Konto, das mit dieser E-Mail-Adresse verknüpft ist.'
-lead: 'Um dich in dein Konto einzuloggen, klicke auf den großen schwarzen Button unten:'
-text-lead: 'Um dich in dein Konto einzuloggen, klicke auf den Link unten:'
-button: Anmelden
-closing: "Mehr muss nicht getan werden."
diff --git a/sites/backend/src/templates/email/signup-aea/en.json b/sites/backend/src/templates/email/signup-aea/en.json
new file mode 100644
index 00000000000..b71b264d781
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aea/en.json
@@ -0,0 +1,9 @@
+{
+ "subject": "[FreeSewing] No need to sign up, you're already in",
+ "heading": "Welcome back to FreeSewing",
+ "preLead": "Someone (you?) tried to sign up with this email address. But we already have an active account tied to this email.",
+ "lead": "To log in to your account, click the big black button below:",
+ "text-lead": "To log in to your account, click the link below:",
+ "button": "Log in",
+ "closing": "That's all it takes."
+}
diff --git a/sites/backend/src/templates/email/signup-aea/en.yaml b/sites/backend/src/templates/email/signup-aea/en.yaml
deleted file mode 100644
index edff52d6da4..00000000000
--- a/sites/backend/src/templates/email/signup-aea/en.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-subject: "[FreeSewing] No need to sign up, you're already in"
-heading: Welcome back to FreeSewing
-preLead: 'Someone (you?) tried to sign up with this email address. But we already have an active account tied to this email.'
-lead: 'To log in to your account, click the big black button below:'
-text-lead: 'To log in to your account, click the link below:'
-button: Log in
-closing: "That's all it takes."
diff --git a/sites/backend/src/templates/email/signup-aea/es.json b/sites/backend/src/templates/email/signup-aea/es.json
new file mode 100644
index 00000000000..4817751f3a8
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aea/es.json
@@ -0,0 +1,9 @@
+{
+ "subject": "[FreeSewing] No hace falta que te inscribas, ya estás dentro",
+ "heading": "Bienvenido de nuevo a FreeSewing",
+ "preLead": "Alguien (¿tú?) ha intentado registrarse con esta dirección de correo electrónico. Pero ya tenemos una cuenta activa vinculada a este correo electrónico.",
+ "lead": "Para acceder a tu cuenta, haz clic en el botón negro grande de abajo:",
+ "text-lead": "Para acceder a tu cuenta, haz clic en el siguiente enlace:",
+ "button": "Iniciar sesión",
+ "closing": "Eso es todo lo que hace falta."
+}
diff --git a/sites/backend/src/templates/email/signup-aea/es.yaml b/sites/backend/src/templates/email/signup-aea/es.yaml
deleted file mode 100644
index 20aff952fc6..00000000000
--- a/sites/backend/src/templates/email/signup-aea/es.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-subject: "[FreeSewing] No hace falta que te inscribas, ya estás dentro"
-heading: Bienvenido de nuevo a FreeSewing
-preLead: 'Alguien (¿tú?) ha intentado registrarse con esta dirección de correo electrónico. Pero ya tenemos una cuenta activa vinculada a este correo electrónico.'
-lead: 'Para acceder a tu cuenta, haz clic en el botón negro grande de abajo:'
-text-lead: 'Para acceder a tu cuenta, haz clic en el siguiente enlace:'
-button: Iniciar sesión
-closing: "Eso es todo lo que hace falta."
diff --git a/sites/backend/src/templates/email/signup-aea/fr.json b/sites/backend/src/templates/email/signup-aea/fr.json
new file mode 100644
index 00000000000..1be3e5fae98
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aea/fr.json
@@ -0,0 +1,9 @@
+{
+ "subject": "[FreeSewing] Pas besoin de s'inscrire, tu es déjà inscrit",
+ "heading": "Bienvenue sur FreeSewing",
+ "preLead": "Quelqu'un (toi ?) a essayé de s'inscrire avec cette adresse e-mail. Mais nous avons déjà un compte actif lié à cet email.",
+ "lead": "Pour te connecter à ton compte, clique sur le gros bouton noir ci-dessous :",
+ "text-lead": "Pour te connecter à ton compte, clique sur le lien ci-dessous :",
+ "button": "Connexion",
+ "closing": "C'est tout ce qu'il faut."
+}
diff --git a/sites/backend/src/templates/email/signup-aea/fr.yaml b/sites/backend/src/templates/email/signup-aea/fr.yaml
deleted file mode 100644
index e6b49d4f317..00000000000
--- a/sites/backend/src/templates/email/signup-aea/fr.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-subject: "[FreeSewing] Pas besoin de s'inscrire, tu es déjà inscrit"
-heading: Bienvenue sur FreeSewing
-preLead: 'Quelqu''un (toi ?) a essayé de s''inscrire avec cette adresse e-mail. Mais nous avons déjà un compte actif lié à cet email.'
-lead: 'Pour te connecter à ton compte, clique sur le gros bouton noir ci-dessous :'
-text-lead: 'Pour te connecter à ton compte, clique sur le lien ci-dessous :'
-button: Connexion
-closing: "C'est tout ce qu'il faut."
diff --git a/sites/backend/src/templates/email/signup-aea/index.mjs b/sites/backend/src/templates/email/signup-aea/index.mjs
index 7e49af81b2c..b5ad490d4bd 100644
--- a/sites/backend/src/templates/email/signup-aea/index.mjs
+++ b/sites/backend/src/templates/email/signup-aea/index.mjs
@@ -1,10 +1,11 @@
import { buttonRow, closingRow, headingRow, preLeadRow, wrap } from '../shared/blocks.mjs'
// Translations
-import en from '../../../../public/locales/en/signup-aea.json' assert { type: 'json' }
-import de from '../../../../public/locales/de/signup-aea.json' assert { type: 'json' }
-import es from '../../../../public/locales/es/signup-aea.json' assert { type: 'json' }
-import fr from '../../../../public/locales/fr/signup-aea.json' assert { type: 'json' }
-import nl from '../../../../public/locales/nl/signup-aea.json' assert { type: 'json' }
+import en from './en.json' assert { type: 'json' }
+import de from './de.json' assert { type: 'json' }
+import es from './es.json' assert { type: 'json' }
+import fr from './fr.json' assert { type: 'json' }
+import nl from './nl.json' assert { type: 'json' }
+import uk from './uk.json' assert { type: 'json' }
// aea = Account Exists and is Active
export const signupaea = {
@@ -32,4 +33,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}}
`),
}
-export const translations = { en, de, es, fr, nl }
+export const translations = { en, de, es, fr, nl, uk }
diff --git a/sites/backend/src/templates/email/signup-aea/nl.json b/sites/backend/src/templates/email/signup-aea/nl.json
new file mode 100644
index 00000000000..273a4a5c3e5
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aea/nl.json
@@ -0,0 +1,9 @@
+{
+ "subject": "[FreeSewing] Je hoeft je niet aan te melden, je bent al binnen",
+ "heading": "Welkom terug bij FreeSewing",
+ "preLead": "Iemand (jij?) probeerde zich aan te melden met dit e-mailadres. Maar we hebben al een actieve account gekoppeld aan dit e-mailadres.",
+ "lead": "Klik op de grote zwarte knop hieronder om in te loggen op je account:",
+ "text-lead": "Klik op de onderstaande link om in te loggen op je account:",
+ "button": "Aanmelden",
+ "closing": "Langer hoeft dat niet te duren."
+}
diff --git a/sites/backend/src/templates/email/signup-aea/nl.yaml b/sites/backend/src/templates/email/signup-aea/nl.yaml
deleted file mode 100644
index f0b0bbe29d8..00000000000
--- a/sites/backend/src/templates/email/signup-aea/nl.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-subject: "[FreeSewing] Je hoeft je niet aan te melden, je bent al binnen"
-heading: Welkom terug bij FreeSewing
-preLead: 'Iemand (jij?) probeerde zich aan te melden met dit e-mailadres. Maar we hebben al een actieve account gekoppeld aan dit e-mailadres.'
-lead: 'Klik op de grote zwarte knop hieronder om in te loggen op je account:'
-text-lead: 'Klik op de onderstaande link om in te loggen op je account:'
-button: Aanmelden
-closing: "Langer hoeft dat niet te duren."
diff --git a/sites/backend/src/templates/email/signup-aea/uk.json b/sites/backend/src/templates/email/signup-aea/uk.json
new file mode 100644
index 00000000000..0b598b4f34a
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aea/uk.json
@@ -0,0 +1,9 @@
+{
+ "subject": "[FreeSewing] Не потрібно реєструватися, ви вже є учасником",
+ "heading": "Ласкаво просимо до FreeSewing",
+ "preLead": "Хтось (ви?) намагався зареєструватися за цією адресою. Але у нас вже є активний акаунт, прив'язаний до цієї адреси.",
+ "lead": "Щоб увійти до свого облікового запису, натисніть велику чорну кнопку нижче:",
+ "text-lead": "Щоб увійти до свого облікового запису, натисніть на посилання нижче:",
+ "button": "Увійти",
+ "closing": "Це все, що потрібно."
+}
diff --git a/sites/backend/src/templates/email/signup-aea/uk.yaml b/sites/backend/src/templates/email/signup-aea/uk.yaml
deleted file mode 100644
index 8fbfcc4634e..00000000000
--- a/sites/backend/src/templates/email/signup-aea/uk.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-subject: "[FreeSewing] Не потрібно реєструватися, ви вже є учасником"
-heading: Ласкаво просимо до FreeSewing
-preLead: 'Хтось (ви?) намагався зареєструватися за цією адресою. Але у нас вже є активний акаунт, прив''язаний до цієї адреси.'
-lead: 'Щоб увійти до свого облікового запису, натисніть велику чорну кнопку нижче:'
-text-lead: 'Щоб увійти до свого облікового запису, натисніть на посилання нижче:'
-button: Увійти
-closing: "Це все, що потрібно."
diff --git a/sites/backend/src/templates/email/signup-aed/de.json b/sites/backend/src/templates/email/signup-aed/de.json
new file mode 100644
index 00000000000..e61bbc06f79
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aed/de.json
@@ -0,0 +1,7 @@
+{
+ "subject": "[FreeSewing] Dein Konto ist als deaktiviert markiert",
+ "heading": "Dein FreeSewing-Konto ist deaktiviert",
+ "preLead": "Ein Konto kann deaktiviert werden, wenn ein/e Nutzer/in seine/ihre Zustimmung widerruft oder (in Ausnahmefällen) wenn ein/e Administrator/in das Konto deaktiviert.",
+ "lead": "In jedem Fall ist die einzige Möglichkeit, ein deaktiviertes Konto wieder zu aktivieren, den Support zu kontaktieren.",
+ "closing": "Um den Support zu kontaktieren, kannst du auf diese E-Mail antworten."
+}
diff --git a/sites/backend/src/templates/email/signup-aed/de.yaml b/sites/backend/src/templates/email/signup-aed/de.yaml
deleted file mode 100644
index a715e393b8e..00000000000
--- a/sites/backend/src/templates/email/signup-aed/de.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-subject: '[FreeSewing] Dein Konto ist als deaktiviert markiert'
-heading: Dein FreeSewing-Konto ist deaktiviert
-preLead: 'Ein Konto kann deaktiviert werden, wenn ein/e Nutzer/in seine/ihre Zustimmung widerruft oder (in Ausnahmefällen) wenn ein/e Administrator/in das Konto deaktiviert.'
-lead: 'In jedem Fall ist die einzige Möglichkeit, ein deaktiviertes Konto wieder zu aktivieren, den Support zu kontaktieren.'
-closing: 'Um den Support zu kontaktieren, kannst du auf diese E-Mail antworten.'
diff --git a/sites/backend/src/templates/email/signup-aed/en.json b/sites/backend/src/templates/email/signup-aed/en.json
new file mode 100644
index 00000000000..9443471dbce
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aed/en.json
@@ -0,0 +1,7 @@
+{
+ "subject": "[FreeSewing] Your account is marked as disabled",
+ "heading": "Your FreeSewing account is disabled",
+ "preLead": "An account can become disabled when a user revokes consent, or (exceptionally) when an administrator disables it.",
+ "lead": "In any case, the only way to re-enable a disabled account is to reach out to support.",
+ "closing": "To contact support, you can reply to this email."
+}
diff --git a/sites/backend/src/templates/email/signup-aed/en.yaml b/sites/backend/src/templates/email/signup-aed/en.yaml
deleted file mode 100644
index 1348808394a..00000000000
--- a/sites/backend/src/templates/email/signup-aed/en.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-subject: '[FreeSewing] Your account is marked as disabled'
-heading: Your FreeSewing account is disabled
-preLead: 'An account can become disabled when a user revokes consent, or (exceptionally) when an administrator disables it.'
-lead: 'In any case, the only way to re-enable a disabled account is to reach out to support.'
-closing: 'To contact support, you can reply to this email.'
diff --git a/sites/backend/src/templates/email/signup-aed/es.json b/sites/backend/src/templates/email/signup-aed/es.json
new file mode 100644
index 00000000000..5be9f6617b6
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aed/es.json
@@ -0,0 +1,7 @@
+{
+ "subject": "[FreeSewing] Tu cuenta está marcada como desactivada",
+ "heading": "Tu cuenta de FreeSewing está desactivada",
+ "preLead": "Una cuenta puede desactivarse cuando un usuario revoca su consentimiento, o (excepcionalmente) cuando un administrador la desactiva.",
+ "lead": "En cualquier caso, la única forma de volver a activar una cuenta desactivada es ponerse en contacto con el servicio de asistencia.",
+ "closing": "Para ponerte en contacto con el servicio de asistencia, puedes responder a este correo electrónico."
+}
diff --git a/sites/backend/src/templates/email/signup-aed/es.yaml b/sites/backend/src/templates/email/signup-aed/es.yaml
deleted file mode 100644
index 0b94cfd32ea..00000000000
--- a/sites/backend/src/templates/email/signup-aed/es.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-subject: '[FreeSewing] Tu cuenta está marcada como desactivada'
-heading: Tu cuenta de FreeSewing está desactivada
-preLead: 'Una cuenta puede desactivarse cuando un usuario revoca su consentimiento, o (excepcionalmente) cuando un administrador la desactiva.'
-lead: 'En cualquier caso, la única forma de volver a activar una cuenta desactivada es ponerse en contacto con el servicio de asistencia.'
-closing: 'Para ponerte en contacto con el servicio de asistencia, puedes responder a este correo electrónico.'
diff --git a/sites/backend/src/templates/email/signup-aed/fr.json b/sites/backend/src/templates/email/signup-aed/fr.json
new file mode 100644
index 00000000000..d8640bafd6d
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aed/fr.json
@@ -0,0 +1,7 @@
+{
+ "subject": "[FreeSewing] Ton compte est marqué comme désactivé",
+ "heading": "Ton compte FreeSewing est désactivé",
+ "preLead": "Un compte peut être désactivé lorsqu'un utilisateur révoque son consentement ou (exceptionnellement) lorsqu'un administrateur le désactive.",
+ "lead": "Dans tous les cas, la seule façon de réactiver un compte désactivé est de tendre la main à l'assistance.",
+ "closing": "Pour contacter l'assistance, tu peux répondre à cet e-mail."
+}
diff --git a/sites/backend/src/templates/email/signup-aed/fr.yaml b/sites/backend/src/templates/email/signup-aed/fr.yaml
deleted file mode 100644
index 9b0ee3c0274..00000000000
--- a/sites/backend/src/templates/email/signup-aed/fr.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-subject: '[FreeSewing] Ton compte est marqué comme désactivé'
-heading: Ton compte FreeSewing est désactivé
-preLead: 'Un compte peut être désactivé lorsqu''un utilisateur révoque son consentement ou (exceptionnellement) lorsqu''un administrateur le désactive.'
-lead: 'Dans tous les cas, la seule façon de réactiver un compte désactivé est de tendre la main à l''assistance.'
-closing: 'Pour contacter l''assistance, tu peux répondre à cet e-mail.'
diff --git a/sites/backend/src/templates/email/signup-aed/index.mjs b/sites/backend/src/templates/email/signup-aed/index.mjs
index 9921668c794..e9d0f781ce1 100644
--- a/sites/backend/src/templates/email/signup-aed/index.mjs
+++ b/sites/backend/src/templates/email/signup-aed/index.mjs
@@ -1,10 +1,11 @@
import { closingRow, headingRow, preLeadRow, wrap } from '../shared/blocks.mjs'
// Translations
-import en from '../../../../public/locales/en/signup-aed.json' assert { type: 'json' }
-import de from '../../../../public/locales/de/signup-aed.json' assert { type: 'json' }
-import es from '../../../../public/locales/es/signup-aed.json' assert { type: 'json' }
-import fr from '../../../../public/locales/fr/signup-aed.json' assert { type: 'json' }
-import nl from '../../../../public/locales/nl/signup-aed.json' assert { type: 'json' }
+import en from './en.json' assert { type: 'json' }
+import de from './de.json' assert { type: 'json' }
+import es from './es.json' assert { type: 'json' }
+import fr from './fr.json' assert { type: 'json' }
+import nl from './nl.json' assert { type: 'json' }
+import uk from './uk.json' assert { type: 'json' }
// aed = Account Exists but is Disabled
export const signupaed = {
@@ -20,4 +21,4 @@ ${closingRow.text}
`),
}
-export const translations = { en, de, es, fr, nl }
+export const translations = { en, de, es, fr, nl, uk }
diff --git a/sites/backend/src/templates/email/signup-aed/nl.json b/sites/backend/src/templates/email/signup-aed/nl.json
new file mode 100644
index 00000000000..8ef0140b44c
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aed/nl.json
@@ -0,0 +1,7 @@
+{
+ "subject": "[FreeSewing] Je account is gemarkeerd als uitgeschakeld",
+ "heading": "Je FreeSewing account is uitgeschakeld",
+ "preLead": "Een account kan worden uitgeschakeld wanneer een gebruiker zijn toestemming intrekt, of (uitzonderlijk) wanneer een beheerder het uitschakelt.",
+ "lead": "Hoe dan ook, de enige manier om een uitgeschakeld account weer in te schakelen is door contact op te nemen met support.",
+ "closing": "Om contact op te nemen met ondersteuning, kun je deze e-mail beantwoorden."
+}
diff --git a/sites/backend/src/templates/email/signup-aed/nl.yaml b/sites/backend/src/templates/email/signup-aed/nl.yaml
deleted file mode 100644
index 4bb4091348d..00000000000
--- a/sites/backend/src/templates/email/signup-aed/nl.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-subject: '[FreeSewing] Je account is gemarkeerd als uitgeschakeld'
-heading: Je FreeSewing account is uitgeschakeld
-preLead: 'Een account kan worden uitgeschakeld wanneer een gebruiker zijn toestemming intrekt, of (uitzonderlijk) wanneer een beheerder het uitschakelt.'
-lead: 'Hoe dan ook, de enige manier om een uitgeschakeld account weer in te schakelen is door contact op te nemen met support.'
-closing: 'Om contact op te nemen met ondersteuning, kun je deze e-mail beantwoorden.'
diff --git a/sites/backend/src/templates/email/signup-aed/uk.json b/sites/backend/src/templates/email/signup-aed/uk.json
new file mode 100644
index 00000000000..a498a4da068
--- /dev/null
+++ b/sites/backend/src/templates/email/signup-aed/uk.json
@@ -0,0 +1,7 @@
+{
+ "subject": "[FreeSewing] Ваш обліковий запис позначено як вимкнений",
+ "heading": "Ваш обліковий запис FreeSewing вимкнено",
+ "preLead": "Обліковий запис може бути відключений, коли користувач відкликає свою згоду, або (у виняткових випадках) коли його відключає адміністратор.",
+ "lead": "У будь-якому випадку, єдиний спосіб відновити дію вимкненого акаунта - звернутися до служби підтримки.",
+ "closing": "Щоб зв'язатися зі службою підтримки, ви можете відповісти на цей лист."
+}
diff --git a/sites/backend/src/templates/email/signup-aed/uk.yaml b/sites/backend/src/templates/email/signup-aed/uk.yaml
deleted file mode 100644
index b68a9ff0c60..00000000000
--- a/sites/backend/src/templates/email/signup-aed/uk.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-subject: '[FreeSewing] Ваш обліковий запис позначено як вимкнений'
-heading: Ваш обліковий запис FreeSewing вимкнено
-preLead: 'Обліковий запис може бути відключений, коли користувач відкликає свою згоду, або (у виняткових випадках) коли його відключає адміністратор.'
-lead: 'У будь-якому випадку, єдиний спосіб відновити дію вимкненого акаунта - звернутися до служби підтримки.'
-closing: 'Щоб зв''язатися зі службою підтримки, ви можете відповісти на цей лист.'
diff --git a/sites/backend/src/templates/email/signup/de.json b/sites/backend/src/templates/email/signup/de.json
new file mode 100644
index 00000000000..bff8a65de0b
--- /dev/null
+++ b/sites/backend/src/templates/email/signup/de.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Hier ist dein Anmeldelink für FreeSewing.org",
+ "heading": "FreeSewing beitreten",
+ "lead": "Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf das große schwarze Rechteck unten:",
+ "text-lead": "Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf den Link unten:",
+ "button": "Ein Konto erstellen",
+ "closing": "Das ist alles für den Moment."
+}
diff --git a/sites/backend/src/templates/email/signup/de.yaml b/sites/backend/src/templates/email/signup/de.yaml
deleted file mode 100644
index 943a7b7120b..00000000000
--- a/sites/backend/src/templates/email/signup/de.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Hier ist dein Anmeldelink für FreeSewing.org"
-heading: FreeSewing beitreten
-lead: 'Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf das große schwarze Rechteck unten:'
-text-lead: 'Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf den Link unten:'
-button: Ein Konto erstellen
-closing: "Das ist alles für den Moment."
diff --git a/sites/backend/src/templates/email/signup/en.json b/sites/backend/src/templates/email/signup/en.json
new file mode 100644
index 00000000000..b6bb96f322f
--- /dev/null
+++ b/sites/backend/src/templates/email/signup/en.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Here is your sign-up link for FreeSewing.org",
+ "heading": "Join FreeSewing",
+ "lead": "To create a FreeSewing account linked to this email address, click the big black rectangle below:",
+ "text-lead": "To create a FreeSewing account linked to this email address, click the link below:",
+ "button": "Create an account",
+ "closing": "That's all for now."
+}
diff --git a/sites/backend/src/templates/email/signup/en.yaml b/sites/backend/src/templates/email/signup/en.yaml
deleted file mode 100644
index da9da542e51..00000000000
--- a/sites/backend/src/templates/email/signup/en.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Here is your sign-up link for FreeSewing.org"
-heading: Join FreeSewing
-lead: 'To create a FreeSewing account linked to this email address, click the big black rectangle below:'
-text-lead: 'To create a FreeSewing account linked to this email address, click the link below:'
-button: Create an account
-closing: "That's all for now."
diff --git a/sites/backend/src/templates/email/signup/es.json b/sites/backend/src/templates/email/signup/es.json
new file mode 100644
index 00000000000..aadb316a368
--- /dev/null
+++ b/sites/backend/src/templates/email/signup/es.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Aquí tienes el enlace para inscribirte en FreeSewing.org",
+ "heading": "Únete a FreeSewing",
+ "lead": "Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el rectángulo negro grande de abajo:",
+ "text-lead": "Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el siguiente enlace:",
+ "button": "Crear una cuenta",
+ "closing": "Eso es todo por ahora."
+}
diff --git a/sites/backend/src/templates/email/signup/es.yaml b/sites/backend/src/templates/email/signup/es.yaml
deleted file mode 100644
index fdb8b8c7f24..00000000000
--- a/sites/backend/src/templates/email/signup/es.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Aquí tienes el enlace para inscribirte en FreeSewing.org"
-heading: Únete a FreeSewing
-lead: 'Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el rectángulo negro grande de abajo:'
-text-lead: 'Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el siguiente enlace:'
-button: Crear una cuenta
-closing: "Eso es todo por ahora."
diff --git a/sites/backend/src/templates/email/signup/fr.json b/sites/backend/src/templates/email/signup/fr.json
new file mode 100644
index 00000000000..08e1b625a66
--- /dev/null
+++ b/sites/backend/src/templates/email/signup/fr.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Voici ton lien d'inscription à FreeSewing.org",
+ "heading": "Rejoignez FreeSewing",
+ "lead": "Pour créer un compte FreeSewing lié à cette adresse email, clique sur le grand rectangle noir ci-dessous :",
+ "text-lead": "Pour créer un compte FreeSewing lié à cette adresse e-mail, clique sur le lien ci-dessous :",
+ "button": "Créer un compte",
+ "closing": "C'est tout pour l'instant."
+}
diff --git a/sites/backend/src/templates/email/signup/fr.yaml b/sites/backend/src/templates/email/signup/fr.yaml
deleted file mode 100644
index de8a5a69b7f..00000000000
--- a/sites/backend/src/templates/email/signup/fr.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Voici ton lien d'inscription à FreeSewing.org"
-heading: Rejoignez FreeSewing
-lead: 'Pour créer un compte FreeSewing lié à cette adresse email, clique sur le grand rectangle noir ci-dessous :'
-text-lead: 'Pour créer un compte FreeSewing lié à cette adresse e-mail, clique sur le lien ci-dessous :'
-button: Créer un compte
-closing: "C'est tout pour l'instant."
diff --git a/sites/backend/src/templates/email/signup/index.mjs b/sites/backend/src/templates/email/signup/index.mjs
index 43a7a2801c4..1b09841763f 100644
--- a/sites/backend/src/templates/email/signup/index.mjs
+++ b/sites/backend/src/templates/email/signup/index.mjs
@@ -1,10 +1,11 @@
import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs'
// Translations
-import en from '../../../../public/locales/en/signup.json' assert { type: 'json' }
-import de from '../../../../public/locales/de/signup.json' assert { type: 'json' }
-import es from '../../../../public/locales/es/signup.json' assert { type: 'json' }
-import fr from '../../../../public/locales/fr/signup.json' assert { type: 'json' }
-import nl from '../../../../public/locales/nl/signup.json' assert { type: 'json' }
+import en from './en.json' assert { type: 'json' }
+import de from './de.json' assert { type: 'json' }
+import es from './es.json' assert { type: 'json' }
+import fr from './fr.json' assert { type: 'json' }
+import nl from './nl.json' assert { type: 'json' }
+import uk from './uk.json' assert { type: 'json' }
export const signup = {
html: wrap.html(`
@@ -29,4 +30,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}}
`),
}
-export const translations = { en, de, es, fr, nl }
+export const translations = { en, de, es, fr, nl, uk }
diff --git a/sites/backend/src/templates/email/signup/nl.json b/sites/backend/src/templates/email/signup/nl.json
new file mode 100644
index 00000000000..975c175b867
--- /dev/null
+++ b/sites/backend/src/templates/email/signup/nl.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Hier is je aanmeldlink voor FreeSewing.org",
+ "heading": "Word lid van FreeSewing",
+ "lead": "Klik op de grote zwarte rechthoek hieronder om een FreeSewing account aan dit e-mailadres te koppelen:",
+ "text-lead": "Klik op de onderstaande link om een FreeSewing account te maken dat is gekoppeld aan dit e-mailadres:",
+ "button": "Maak een account aan",
+ "closing": "Dat is alles voor nu."
+}
diff --git a/sites/backend/src/templates/email/signup/nl.yaml b/sites/backend/src/templates/email/signup/nl.yaml
deleted file mode 100644
index 9d4e38d3482..00000000000
--- a/sites/backend/src/templates/email/signup/nl.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Hier is je aanmeldlink voor FreeSewing.org"
-heading: Word lid van FreeSewing
-lead: 'Klik op de grote zwarte rechthoek hieronder om een FreeSewing account aan dit e-mailadres te koppelen:'
-text-lead: 'Klik op de onderstaande link om een FreeSewing account te maken dat is gekoppeld aan dit e-mailadres:'
-button: Maak een account aan
-closing: "Dat is alles voor nu."
diff --git a/sites/backend/src/templates/email/signup/uk.json b/sites/backend/src/templates/email/signup/uk.json
new file mode 100644
index 00000000000..ceaeaa5f9f0
--- /dev/null
+++ b/sites/backend/src/templates/email/signup/uk.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Ось ваше посилання для реєстрації на FreeSewing.org",
+ "heading": "Приєднатися до FreeSewing",
+ "lead": "Щоб створити обліковий запис FreeSewing, пов'язаний з цією адресою електронної пошти, натисніть великий чорний прямокутник нижче:",
+ "text-lead": "Щоб створити обліковий запис FreeSewing, пов'язаний з цією електронною адресою, натисніть на посилання нижче:",
+ "button": "Створіть обліковий запис",
+ "closing": "Наразі це все."
+}
diff --git a/sites/backend/src/templates/email/signup/uk.yaml b/sites/backend/src/templates/email/signup/uk.yaml
deleted file mode 100644
index 2c930cbddf4..00000000000
--- a/sites/backend/src/templates/email/signup/uk.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Ось ваше посилання для реєстрації на FreeSewing.org"
-heading: Приєднатися до FreeSewing
-lead: 'Щоб створити обліковий запис FreeSewing, пов''язаний з цією адресою електронної пошти, натисніть великий чорний прямокутник нижче:'
-text-lead: 'Щоб створити обліковий запис FreeSewing, пов''язаний з цією електронною адресою, натисніть на посилання нижче:'
-button: Створіть обліковий запис
-closing: "Наразі це все."
diff --git a/sites/backend/src/templates/email/transinvite/de.json b/sites/backend/src/templates/email/transinvite/de.json
new file mode 100644
index 00000000000..ed62f0d0a44
--- /dev/null
+++ b/sites/backend/src/templates/email/transinvite/de.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Deine Einladung, dem FreeSewing-Übersetzungsteam beizutreten",
+ "heading": "Trete einem FreeSewing-Übersetzungsteam bei",
+ "lead": "Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf das große schwarze Rechteck unten:",
+ "text-lead": "Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf den untenstehenden Link:",
+ "button": "Trete dem Übersetzungsteam bei",
+ "closing": "So kommst du zu Crowdin, der von uns genutzten Übersetzungsplattform."
+}
diff --git a/sites/backend/src/templates/email/transinvite/de.yaml b/sites/backend/src/templates/email/transinvite/de.yaml
deleted file mode 100644
index 0790fd41ac0..00000000000
--- a/sites/backend/src/templates/email/transinvite/de.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Deine Einladung, dem FreeSewing-Übersetzungsteam beizutreten"
-heading: Trete einem FreeSewing-Übersetzungsteam bei
-lead: 'Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf das große schwarze Rechteck unten:'
-text-lead: 'Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf den untenstehenden Link:'
-button: Trete dem Übersetzungsteam bei
-closing: "So kommst du zu Crowdin, der von uns genutzten Übersetzungsplattform."
diff --git a/sites/backend/src/templates/email/transinvite/en.json b/sites/backend/src/templates/email/transinvite/en.json
new file mode 100644
index 00000000000..8514b51bf3b
--- /dev/null
+++ b/sites/backend/src/templates/email/transinvite/en.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Your invitation to join FreeSewing's the translation team",
+ "heading": "Join a FreeSewing translation team",
+ "lead": "To join the FreeSewing translation team, click the big black rectangle below:",
+ "text-lead": "To join the FreeSewing translation team, click the link below:",
+ "button": "Join the translation team",
+ "closing": "This will take you to Crowdin, the translation platform we use."
+}
diff --git a/sites/backend/src/templates/email/transinvite/en.yaml b/sites/backend/src/templates/email/transinvite/en.yaml
deleted file mode 100644
index 08af7f8536d..00000000000
--- a/sites/backend/src/templates/email/transinvite/en.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Your invitation to join FreeSewing's the translation team"
-heading: Join a FreeSewing translation team
-lead: 'To join the FreeSewing translation team, click the big black rectangle below:'
-text-lead: 'To join the FreeSewing translation team, click the link below:'
-button: Join the translation team
-closing: "This will take you to Crowdin, the translation platform we use."
diff --git a/sites/backend/src/templates/email/transinvite/es.json b/sites/backend/src/templates/email/transinvite/es.json
new file mode 100644
index 00000000000..70ba9986337
--- /dev/null
+++ b/sites/backend/src/templates/email/transinvite/es.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Tu invitación para unirte al equipo de traducción de FreeSewing",
+ "heading": "Únete a un equipo de traducción de FreeSewing",
+ "lead": "Para unirte al equipo de traducción de FreeSewing, haz clic en el rectángulo negro grande de abajo:",
+ "text-lead": "Para unirte al equipo de traducción de FreeSewing, haz clic en el siguiente enlace:",
+ "button": "Únete al equipo de traducción",
+ "closing": "Esto te llevará a Crowdin, la plataforma de traducción que utilizamos."
+}
diff --git a/sites/backend/src/templates/email/transinvite/es.yaml b/sites/backend/src/templates/email/transinvite/es.yaml
deleted file mode 100644
index 33a62412605..00000000000
--- a/sites/backend/src/templates/email/transinvite/es.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Tu invitación para unirte al equipo de traducción de FreeSewing"
-heading: Únete a un equipo de traducción de FreeSewing
-lead: 'Para unirte al equipo de traducción de FreeSewing, haz clic en el rectángulo negro grande de abajo:'
-text-lead: 'Para unirte al equipo de traducción de FreeSewing, haz clic en el siguiente enlace:'
-button: Únete al equipo de traducción
-closing: "Esto te llevará a Crowdin, la plataforma de traducción que utilizamos."
diff --git a/sites/backend/src/templates/email/transinvite/fr.json b/sites/backend/src/templates/email/transinvite/fr.json
new file mode 100644
index 00000000000..a1faa163102
--- /dev/null
+++ b/sites/backend/src/templates/email/transinvite/fr.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Ton invitation à rejoindre l'équipe de traduction de FreeSewing",
+ "heading": "Rejoins une équipe de traduction FreeSewing",
+ "lead": "Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le grand rectangle noir ci-dessous :",
+ "text-lead": "Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le lien ci-dessous :",
+ "button": "Rejoins l'équipe de traduction",
+ "closing": "Cela te mènera à Crowdin, la plateforme de traduction que nous utilisons."
+}
diff --git a/sites/backend/src/templates/email/transinvite/fr.yaml b/sites/backend/src/templates/email/transinvite/fr.yaml
deleted file mode 100644
index f306c1c1bcd..00000000000
--- a/sites/backend/src/templates/email/transinvite/fr.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Ton invitation à rejoindre l'équipe de traduction de FreeSewing"
-heading: Rejoins une équipe de traduction FreeSewing
-lead: 'Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le grand rectangle noir ci-dessous :'
-text-lead: 'Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le lien ci-dessous :'
-button: Rejoins l'équipe de traduction
-closing: "Cela te mènera à Crowdin, la plateforme de traduction que nous utilisons."
diff --git a/sites/backend/src/templates/email/transinvite/index.mjs b/sites/backend/src/templates/email/transinvite/index.mjs
index 7c42889e504..c43c823af8b 100644
--- a/sites/backend/src/templates/email/transinvite/index.mjs
+++ b/sites/backend/src/templates/email/transinvite/index.mjs
@@ -1,10 +1,11 @@
import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs'
// Translations
-import en from '../../../../public/locales/en/transinvite.json' assert { type: 'json' }
-import de from '../../../../public/locales/de/transinvite.json' assert { type: 'json' }
-import es from '../../../../public/locales/es/transinvite.json' assert { type: 'json' }
-import fr from '../../../../public/locales/fr/transinvite.json' assert { type: 'json' }
-import nl from '../../../../public/locales/nl/transinvite.json' assert { type: 'json' }
+import en from './en.json' assert { type: 'json' }
+import de from './de.json' assert { type: 'json' }
+import es from './es.json' assert { type: 'json' }
+import fr from './fr.json' assert { type: 'json' }
+import nl from './nl.json' assert { type: 'json' }
+import uk from './uk.json' assert { type: 'json' }
export const transinvite = {
html: wrap.html(`
@@ -29,4 +30,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}}
`),
}
-export const translations = { en, de, es, fr, nl }
+export const translations = { en, de, es, fr, nl, uk }
diff --git a/sites/backend/src/templates/email/transinvite/nl.json b/sites/backend/src/templates/email/transinvite/nl.json
new file mode 100644
index 00000000000..9eabfaad43c
--- /dev/null
+++ b/sites/backend/src/templates/email/transinvite/nl.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Je uitnodiging om deel te nemen aan het vertaalteam van FreeSewing",
+ "heading": "Word lid van een FreeSewing vertaalteam",
+ "lead": "Klik op de grote zwarte rechthoek hieronder om lid te worden van het vertaalteam van FreeSewing:",
+ "text-lead": "Klik op de onderstaande link om lid te worden van het vertaalteam van FreeSewing:",
+ "button": "Word lid van het vertaalteam",
+ "closing": "Dit brengt je naar Crowdin, het vertaalplatform dat we gebruiken."
+}
diff --git a/sites/backend/src/templates/email/transinvite/nl.yaml b/sites/backend/src/templates/email/transinvite/nl.yaml
deleted file mode 100644
index a88364029c1..00000000000
--- a/sites/backend/src/templates/email/transinvite/nl.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Je uitnodiging om deel te nemen aan het vertaalteam van FreeSewing"
-heading: Word lid van een FreeSewing vertaalteam
-lead: 'Klik op de grote zwarte rechthoek hieronder om lid te worden van het vertaalteam van FreeSewing:'
-text-lead: 'Klik op de onderstaande link om lid te worden van het vertaalteam van FreeSewing:'
-button: Word lid van het vertaalteam
-closing: "Dit brengt je naar Crowdin, het vertaalplatform dat we gebruiken."
diff --git a/sites/backend/src/templates/email/transinvite/uk.json b/sites/backend/src/templates/email/transinvite/uk.json
new file mode 100644
index 00000000000..5fd2a86313c
--- /dev/null
+++ b/sites/backend/src/templates/email/transinvite/uk.json
@@ -0,0 +1,8 @@
+{
+ "subject": "[FreeSewing] Ваше запрошення приєднатися до команди перекладачів FreeSewing",
+ "heading": "Приєднуйтесь до команди перекладачів FreeSewing",
+ "lead": "Щоб приєднатися до команди перекладачів FreeSewing, натисніть великий чорний прямокутник нижче:",
+ "text-lead": "Щоб приєднатися до команди перекладачів FreeSewing, натисніть на посилання нижче:",
+ "button": "Приєднуйтесь до команди перекладачів",
+ "closing": "Ви потрапите на Crowdin, платформу для перекладу, яку ми використовуємо."
+}
diff --git a/sites/backend/src/templates/email/transinvite/uk.yaml b/sites/backend/src/templates/email/transinvite/uk.yaml
deleted file mode 100644
index 892cfc20749..00000000000
--- a/sites/backend/src/templates/email/transinvite/uk.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-subject: "[FreeSewing] Ваше запрошення приєднатися до команди перекладачів FreeSewing"
-heading: Приєднуйтесь до команди перекладачів FreeSewing
-lead: 'Щоб приєднатися до команди перекладачів FreeSewing, натисніть великий чорний прямокутник нижче:'
-text-lead: 'Щоб приєднатися до команди перекладачів FreeSewing, натисніть на посилання нижче:'
-button: Приєднуйтесь до команди перекладачів
-closing: "Ви потрапите на Crowdin, платформу для перекладу, яку ми використовуємо."
diff --git a/sites/backend/src/templates/email/uk.json b/sites/backend/src/templates/email/uk.json
new file mode 100644
index 00000000000..fabf381f4c8
--- /dev/null
+++ b/sites/backend/src/templates/email/uk.json
@@ -0,0 +1,10 @@
+{
+ "greeting": "з любов'ю",
+ "ps-pre-link": "FreeSewing безкоштовний, але, будь ласка",
+ "ps-link": "стати патроном",
+ "ps-post-link": "якщо можеш собі це дозволити.",
+ "text-ps": "FreeSewing є безкоштовним, але, будь ласка, станьте меценатом, якщо ви можете собі це дозволити.",
+ "notMarketing": "Це не маркетинговий, а транзакційний лист про ваш обліковий запис FreeSewing.",
+ "seeWhy": "Для отримання додаткової інформації див:",
+ "whyDidIGetThis": "Чому я отримав цей лист?"
+}
diff --git a/sites/backend/src/templates/email/uk.yaml b/sites/backend/src/templates/email/uk.yaml
deleted file mode 100644
index 1f72815b64f..00000000000
--- a/sites/backend/src/templates/email/uk.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-#Shared
-greeting: з любов'ю
-ps-pre-link: FreeSewing безкоштовний, але, будь ласка
-ps-link: стати патроном
-ps-post-link: якщо можеш собі це дозволити.
-text-ps: 'FreeSewing є безкоштовним, але, будь ласка, станьте меценатом, якщо ви можете собі це дозволити.'
-notMarketing: Це не маркетинговий, а транзакційний лист про ваш обліковий запис FreeSewing.
-seeWhy: 'Для отримання додаткової інформації див:'
-whyDidIGetThis: Чому я отримав цей лист?
diff --git a/sites/backend/src/utils/email.mjs b/sites/backend/src/utils/email.mjs
index c3c957fcfaf..f4f1f67dc88 100644
--- a/sites/backend/src/utils/email.mjs
+++ b/sites/backend/src/utils/email.mjs
@@ -2,6 +2,7 @@ import { templates, translations } from '../templates/email/index.mjs'
import { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2'
import mustache from 'mustache'
import { log } from './log.mjs'
+console.log(Object.keys(templates))
/*
* Exporting this closure that makes sure we have access to the
@@ -25,7 +26,8 @@ async function sendEmailViaAwsSes(
) {
// Make sure we have what it takes
if (!template || !to || typeof templates[template] === 'undefined') {
- log.warn(`Tried to email invalid template: ${template}`)
+ if (!to) log.warn(`A To: address is mandatory when sending email`)
+ else log.warn(`Tried to email invalid template: ${template}`)
return false
}
diff --git a/sites/backend/tests/index.mjs b/sites/backend/tests/index.mjs
index a2e3f1bff98..eb37459baab 100644
--- a/sites/backend/tests/index.mjs
+++ b/sites/backend/tests/index.mjs
@@ -5,16 +5,18 @@ import { apikeyTests } from './apikey.mjs'
import { setTests } from './set.mjs'
import { curatedSetTests } from './curated-set.mjs'
import { patternTests } from './pattern.mjs'
+import { subscriberTests } from './subscriber.mjs'
import { setup } from './shared.mjs'
const runTests = async (...params) => {
- await userTests(...params)
- await mfaTests(...params)
- await apikeyTests(...params)
- await accountTests(...params)
- await setTests(...params)
- await curatedSetTests(...params)
- await patternTests(...params)
+ //await userTests(...params)
+ //await mfaTests(...params)
+ //await apikeyTests(...params)
+ //await accountTests(...params)
+ //await setTests(...params)
+ //await curatedSetTests(...params)
+ //await patternTests(...params)
+ await subscriberTests(...params)
}
// Load initial data required for tests
diff --git a/sites/backend/tests/shared.mjs b/sites/backend/tests/shared.mjs
index 6277ad4a94c..c16c3ee9569 100644
--- a/sites/backend/tests/shared.mjs
+++ b/sites/backend/tests/shared.mjs
@@ -41,6 +41,7 @@ export const setup = async () => {
key: '🎟️ ',
set: '🧕 ',
pattern: '👕 ',
+ subscriber: '📬',
},
randomString,
}
diff --git a/sites/backend/tests/subscriber.mjs b/sites/backend/tests/subscriber.mjs
new file mode 100644
index 00000000000..0c9232f4744
--- /dev/null
+++ b/sites/backend/tests/subscriber.mjs
@@ -0,0 +1,92 @@
+export const subscriberTests = async (chai, config, expect, store) => {
+ describe(`${store.icon('subscriber')} Subscriber tests`, () => {
+ it(`${store.icon('subscriber')} Should not subscribe without an email address`, (done) => {
+ const data = {
+ language: 'nL',
+ test: 'yes please',
+ }
+ chai
+ .request(config.api)
+ .post(`/subscriber`)
+ .send(data)
+ .end((err, res) => {
+ expect(err === null).to.equal(true)
+ expect(res.status).to.equal(400)
+ expect(res.body.result).to.equal('error')
+ expect(res.body.error).to.equal('emailMissing')
+ done()
+ })
+ })
+
+ it(`${store.icon('subscriber')} Should not subscribe without a language`, (done) => {
+ const data = {
+ email: 'joost@FREESEWING.dev',
+ test: 'yes please',
+ }
+ chai
+ .request(config.api)
+ .post(`/subscriber`)
+ .send(data)
+ .end((err, res) => {
+ expect(err === null).to.equal(true)
+ expect(res.status).to.equal(400)
+ expect(res.body.result).to.equal('error')
+ expect(res.body.error).to.equal('languageMissing')
+ done()
+ })
+ })
+
+ it(`${store.icon('subscriber')} Should subscribe`, (done) => {
+ const data = {
+ email: 'joost@FREESEWING.dev',
+ language: 'eN',
+ test: 'yes please',
+ }
+ chai
+ .request(config.api)
+ .post(`/subscriber`)
+ .send(data)
+ .end((err, res) => {
+ expect(err === null).to.equal(true)
+ expect(res.status).to.equal(200)
+ expect(res.body.result).to.equal('success')
+ expect(res.body.data.email).to.equal(data.email.toLowerCase())
+ expect(res.body.data.language).to.equal(data.language.toLowerCase())
+ expect(typeof res.body.data.id).to.equal('string')
+ expect(typeof res.body.data.ehash).to.equal('string')
+ store.subscriber = res.body.data
+ done()
+ })
+ })
+
+ it(`${store.icon('subscriber')} Should confirm a subscription`, (done) => {
+ chai
+ .request(config.api)
+ .put(`/subscriber`)
+ .send({
+ id: store.subscriber.id,
+ ehash: store.subscriber.ehash,
+ })
+ .end((err, res) => {
+ expect(err === null).to.equal(true)
+ expect(res.status).to.equal(200)
+ done()
+ })
+ })
+
+ //it(`${store.icon('subscriber')} Should unsubscribe`, (done) => {
+ // chai
+ // .request(config.api)
+ // .delete(`/subscriber`)
+ // .send({
+ // id: store.subscriber.id,
+ // ehash: store.subscriber.ehash,
+ // })
+ // .end((err, res) => {
+ // expect(err === null).to.equal(true)
+ // expect(res.status).to.equal(200)
+ // done()
+ // })
+ //})
+ })
+}
diff --git a/sites/org/pages/newsletter/index.mjs b/sites/org/pages/newsletter/index.mjs
new file mode 100644
index 00000000000..9cd3289a9b8
--- /dev/null
+++ b/sites/org/pages/newsletter/index.mjs
@@ -0,0 +1,43 @@
+// Dependencies
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
+import { nsMerge } from 'shared/utils.mjs'
+// Hooks
+import { useTranslation } from 'next-i18next'
+// Components
+import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
+import { Popout } from 'shared/components/popout/index.mjs'
+
+// Translation namespaces used on this page
+const namespaces = nsMerge(pageNs, 'newsletter')
+
+/*
+ * Each page MUST be wrapped in the PageWrapper component.
+ * You also MUST spread props.page into this wrapper component
+ * when path and locale come from static props (as here)
+ * or set them manually.
+ */
+const NewsletterPage = ({ page }) => {
+ const { t } = useTranslation(namespaces)
+
+ return (
+
+
+ handle newsletter subscription here
+
+
+ )
+}
+
+export default NewsletterPage
+
+export async function getStaticProps({ locale }) {
+ return {
+ props: {
+ ...(await serverSideTranslations(locale, namespaces)),
+ page: {
+ locale,
+ path: ['newsletter'],
+ },
+ },
+ }
+}
diff --git a/sites/org/pages/newsletter/subscribe/[...tokens].mjs b/sites/org/pages/newsletter/subscribe/[...tokens].mjs
new file mode 100644
index 00000000000..9939e8e4968
--- /dev/null
+++ b/sites/org/pages/newsletter/subscribe/[...tokens].mjs
@@ -0,0 +1,107 @@
+// Dependencies
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
+import { nsMerge } from 'shared/utils.mjs'
+// Hooks
+import { useState, useContext } from 'react'
+import { useTranslation } from 'next-i18next'
+import { useBackend } from 'shared/hooks/use-backend.mjs'
+// Context
+import { LoadingContext } from 'shared/context/loading-context.mjs'
+// Components
+import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
+import { Popout } from 'shared/components/popout/index.mjs'
+import { PageLink } from 'shared/components/page-link.mjs'
+
+// Translation namespaces used on this page
+const namespaces = nsMerge(pageNs, 'newsletter')
+
+/*
+ * Each page MUST be wrapped in the PageWrapper component.
+ * You also MUST spread props.page into this wrapper component
+ * when path and locale come from static props (as here)
+ * or set them manually.
+ */
+const NewsletterPage = ({ page, id, ehash }) => {
+ const { t } = useTranslation(namespaces)
+ const { loading, setLoading } = useContext(LoadingContext)
+ const backend = useBackend()
+
+ const [confirmed, setConfirmed] = useState(false)
+
+ const handler = async () => {
+ setLoading(true)
+ const result = await backend.confirmNewsletterSubscribe({ id, ehash })
+ setLoading(false)
+ setConfirmed(true)
+ }
+
+ return (
+
+
+
+ )
+}
+
+export default NewsletterPage
+
+export async function getStaticProps({ locale, params }) {
+ return {
+ props: {
+ ...(await serverSideTranslations(locale, namespaces)),
+ id: params.tokens[0] || null,
+ ehash: params.tokens[1] || null,
+ page: {
+ locale,
+ path: ['newsletter'],
+ },
+ },
+ }
+}
+
+/*
+ * Do not generate anything statically
+ */
+export async function getStaticPaths() {
+ return {
+ paths: [],
+ fallback: 'blocking',
+ }
+}
diff --git a/sites/shared/components/newsletter/en.yaml b/sites/shared/components/newsletter/en.yaml
new file mode 100644
index 00000000000..a2a0911ed2e
--- /dev/null
+++ b/sites/shared/components/newsletter/en.yaml
@@ -0,0 +1,16 @@
+newsletter: Newsletter
+subscribe: Subscribe
+subscribeConfirm: Confirm you want to subscribe to the FreeSewing newsletter
+subscribeLead: Once you click the button below, your subscription to the FreeSewing newsletter will be active.
+subscribePs: You can unsubscribe at any time with the link below. This unsubscribe link will also be included at the bottom of every newsletter we send you, so you do not need to bookmark it, but you can if you want to.
+subscribeWhy: Why do I have to click again to confirm I want to subscribe after I already clicked the confirmation link you sent me?
+unsubscribeLink: Unsubscribe link
+unsubscribe: Unsubscribe
+unsubscribeConfirm: Confirm you want to unsubscribe from the FreeSewing newsletter
+unsubscribeLead: Once you click the button below, you will be unsubscribed from the FreeSewing newsletter.
+unsubscribeWhy: Why do I have to click again to confirm I want to unsubscribe after I already clicked the newsletter unsubscribe link?
+whyLead: If you are curious why we are making you click yet another time, there is a good reason for that.
+invalidLink: The link you followed to get here is invalid
+faqLead: The answer is covered in our FAQ
+whatsWithTheClicks: What's with all the clicks?
+thanksDone: Thank you, that's all it took.
diff --git a/sites/shared/hooks/use-backend.mjs b/sites/shared/hooks/use-backend.mjs
index 63b8a67d970..0b097569172 100644
--- a/sites/shared/hooks/use-backend.mjs
+++ b/sites/shared/hooks/use-backend.mjs
@@ -302,10 +302,17 @@ Backend.prototype.sendLanguageSuggestion = async function (data) {
}
/*
- * Create payment intent
+ * Confirm newsletter subscribe
*/
-Backend.prototype.createPaymentIntent = async function (data) {
- return responseHandler(await api.post(`/payments/intent`, data), 201)
+Backend.prototype.confirmNewsletterSubscribe = async function ({ id, ehash }) {
+ return responseHandler(await api.put('/subscriber', { id, ehash }))
+}
+
+/*
+ * Confirm newsletter unsubscribe
+ */
+Backend.prototype.confirmNewsletterUnsubscribe = async function ({ id, ehash }) {
+ return responseHandler(await api.delete('/subscriber', { id, ehash }))
}
export function useBackend(token = false) {