diff --git a/backend/src/server/createServer.ts b/backend/src/server/createServer.ts index 9713f6c98..a7f834166 100644 --- a/backend/src/server/createServer.ts +++ b/backend/src/server/createServer.ts @@ -14,7 +14,6 @@ import { GRADIDO_REALM, LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { AppDatabase } from 'database' import { context as serverContext } from './context' import { cors } from './cors' -import { i18n } from './localization' import { plugins } from './plugins' import { jwks, openidConfiguration } from '@/openIDConnect' // TODO implement @@ -74,9 +73,6 @@ export const createServer = async ( app.use(json()) // bodyparser urlencoded for elopage app.use(urlencoded({ extended: true })) - - // i18n - app.use(i18n.init) // Elopage Webhook diff --git a/backend/src/server/localization.ts b/backend/src/server/localization.ts deleted file mode 100644 index 2332f0eaf..000000000 --- a/backend/src/server/localization.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import i18n from 'i18n' -import { getLogger } from 'log4js' - -const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.localization`) - -i18n.configure({ - locales: ['en', 'de'], - defaultLocale: 'en', - retryInDefaultLocale: false, - staticCatalog: { - en: { general: { decimalSeparator: "." } }, - de: { general: { decimalSeparator: "," } }, - }, - // autoReload: true, // if this is activated the seeding hangs at the very end - updateFiles: false, - objectNotation: true, - logDebugFn: (msg) => logger.debug(msg), - logWarnFn: (msg) => logger.info(msg), - logErrorFn: (msg) => logger.error(msg), - // this api is needed for email-template pug files - api: { - __: 't', // now req.__ becomes req.t - __n: 'tn', // and req.__n can be called as req.tn - }, - register: global, - mustacheConfig: { - tags: ['{', '}'], - disable: false, - }, -}) - -export { i18n } diff --git a/core/package.json b/core/package.json index aa777165b..943e81f81 100644 --- a/core/package.json +++ b/core/package.json @@ -22,8 +22,8 @@ "typecheck": "tsc --noEmit", "lint": "biome check --error-on-warnings .", "lint:fix": "biome check --error-on-warnings . --write", - "locales": "scripts/sort.sh src/emails/locales", - "locales:fix": "scripts/sort.sh src/emails/locales --fix", + "locales": "scripts/sort.sh src/locales", + "locales:fix": "scripts/sort.sh src/locales --fix", "clear": "rm -rf node_modules && rm -rf build && rm -rf .turbo" }, "dependencies": { diff --git a/core/src/emails/sendEmailTranslated.test.ts b/core/src/emails/sendEmailTranslated.test.ts index 26f4d6ebd..8d77637ff 100644 --- a/core/src/emails/sendEmailTranslated.test.ts +++ b/core/src/emails/sendEmailTranslated.test.ts @@ -1,6 +1,6 @@ import { createTransport } from 'nodemailer' import { CONFIG } from '../config' -import { i18n } from './localization' +import { i18n } from '../locales/localization' import { getLogger } from '../../../config-schema/test/testSetup.bun' import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const' import { sendEmailTranslated } from './sendEmailTranslated' diff --git a/core/src/emails/sendEmailTranslated.ts b/core/src/emails/sendEmailTranslated.ts index 205ca07c6..c73650fb5 100644 --- a/core/src/emails/sendEmailTranslated.ts +++ b/core/src/emails/sendEmailTranslated.ts @@ -1,6 +1,6 @@ import path from 'path' import Email from 'email-templates' -import { i18n } from './localization' +import { i18n } from '../locales/localization' import { createTransport } from 'nodemailer' import { CONFIG } from '../config' import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const' @@ -113,7 +113,6 @@ export const sendEmailTranslated = async ({ }) .catch((error: unknown) => { logger.error('Error sending notification email', error) - return error }) return resultSend diff --git a/core/src/emails/sendEmailVariants.test.ts b/core/src/emails/sendEmailVariants.test.ts index 86ec556e9..ee7edf936 100644 --- a/core/src/emails/sendEmailVariants.test.ts +++ b/core/src/emails/sendEmailVariants.test.ts @@ -48,6 +48,10 @@ describe('sendEmailVariants', () => { const contributionFrontendLink = 'https://gradido.net/contributions/own-contributions/1#contributionListItem-1' + afterEach(() => { + sendEmailTranslatedSpy.mockClear() + }) + describe('sendAddedContributionMessageEmail', () => { beforeAll(async () => { result = await sendAddedContributionMessageEmail({ @@ -163,7 +167,7 @@ describe('sendEmailVariants', () => { }) }) - /* + describe('sendAccountMultiRegistrationEmail', () => { beforeAll(async () => { @@ -182,20 +186,22 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'accountMultiRegistration', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', resendLink: CONFIG.EMAIL_LINK_FORGOTPASSWORD, supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, communityURL: CONFIG.COMMUNITY_URL, - }, + }), }) }) describe('result', () => { it('is the expected object', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -236,24 +242,26 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'contributionConfirmed', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', senderFirstName: 'Bibi', senderLastName: 'Bloxberg', contributionMemo: 'My contribution.', contributionAmount: '23.54', supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, contributionFrontendLink, - }, + }), }) }) }) describe('result', () => { it('is the expected object', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -293,24 +301,26 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'contributionChangedByModerator', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', senderFirstName: 'Bibi', senderLastName: 'Bloxberg', contributionMemo: 'My contribution.', contributionMemoUpdated: 'This is a better contribution memo.', contributionFrontendLink, supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, - }, + }), }) }) }) describe('result', () => { it('is the expected object', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -349,23 +359,25 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'contributionDenied', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', senderFirstName: 'Bibi', senderLastName: 'Bloxberg', contributionMemo: 'My contribution.', contributionFrontendLink, supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, - }, + }), }) }) }) describe('result', () => { it('has expected result', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -404,23 +416,25 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'contributionDeleted', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', senderFirstName: 'Bibi', senderLastName: 'Bloxberg', contributionMemo: 'My contribution.', contributionFrontendLink, supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, - }, + }), }) }) }) describe('result', () => { it('is the expected object', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -457,23 +471,25 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'resetPassword', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', resetLink: 'http://localhost/reset-password/3762660021544901417', timeDurationObject: { hours: 23, minutes: 30 }, resendLink: CONFIG.EMAIL_LINK_FORGOTPASSWORD, supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, communityURL: CONFIG.COMMUNITY_URL, - }, + }), }) }) }) describe('result', () => { it('is the expected object', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -513,10 +529,10 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'transactionLinkRedeemed', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', senderFirstName: 'Bibi', senderLastName: 'Bloxberg', senderEmail: 'bibi@bloxberg.de', @@ -524,14 +540,16 @@ describe('sendEmailVariants', () => { transactionAmount: '17.65', supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, communityURL: CONFIG.COMMUNITY_URL, - }, + }), }) }) }) describe('result', () => { it('is the expected object', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -571,10 +589,10 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', }, template: 'transactionReceived', - locals: { + locals: expect.objectContaining({ firstName: 'Peter', lastName: 'Lustig', - locale: 'en', + language: 'en', memo: 'Du bist schon lustiger ;)', senderFirstName: 'Bibi', senderLastName: 'Bloxberg', @@ -582,14 +600,16 @@ describe('sendEmailVariants', () => { transactionAmount: '37.40', supportEmail: CONFIG.COMMUNITY_SUPPORT_MAIL, communityURL: CONFIG.COMMUNITY_URL, - }, + }), }) }) }) describe('result', () => { it('is the expected object', () => { - expect(result).toMatchObject({ + // bun testrunner bug, toMatchObject mess with 'result' + const resultClone = JSON.parse(JSON.stringify(result)) + expect(resultClone).toMatchObject({ originalMessage: expect.objectContaining({ to: 'Peter Lustig ', from: 'Gradido (emails.general.doNotAnswer) ', @@ -606,5 +626,4 @@ describe('sendEmailVariants', () => { }) }) }) - */ }) diff --git a/core/src/emails/locales/de.json b/core/src/locales/de.json similarity index 100% rename from core/src/emails/locales/de.json rename to core/src/locales/de.json diff --git a/core/src/emails/locales/en.json b/core/src/locales/en.json similarity index 100% rename from core/src/emails/locales/en.json rename to core/src/locales/en.json diff --git a/core/src/emails/localization.test.ts b/core/src/locales/localization.test.ts similarity index 100% rename from core/src/emails/localization.test.ts rename to core/src/locales/localization.test.ts diff --git a/core/src/emails/localization.ts b/core/src/locales/localization.ts similarity index 65% rename from core/src/emails/localization.ts rename to core/src/locales/localization.ts index 488ae5411..df604cf5a 100644 --- a/core/src/emails/localization.ts +++ b/core/src/locales/localization.ts @@ -1,6 +1,10 @@ -import en from './locales/en.json' -import de from './locales/de.json' +import en from './en.json' +import de from './de.json' import { I18n } from 'i18n' +import { getLogger } from 'log4js' +import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const' + +const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.emails.localization`) function flatten(obj: any, prefix: string = ''): any { const result: any = {} @@ -18,6 +22,9 @@ export const i18n = new I18n({ locales: ['en', 'de'], defaultLocale: 'en', staticCatalog: { en: flatten(en), de: flatten(de) }, + logDebugFn: (msg) => logger.debug(msg), + logWarnFn: (msg) => logger.info(msg), + logErrorFn: (msg) => logger.error(msg), api: { __: 't', // now req.__ becomes req.t __n: 'tn', // and req.__n can be called as req.tn diff --git a/core/src/util/utilities.ts b/core/src/util/utilities.ts index be32736fc..be9e3d898 100644 --- a/core/src/util/utilities.ts +++ b/core/src/util/utilities.ts @@ -1,7 +1,7 @@ import { promisify } from 'util' import { Decimal } from 'decimal.js-light' -import i18n from 'i18n' +import { i18n } from '../locales/localization' export const objectValuesToArray = (obj: Record): string[] => Object.keys(obj).map((key) => obj[key])