From 9e5b729d28e599adee226df34bd8bd9613a78744 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:42:31 +0200 Subject: [PATCH] Refactoring --- apps/api/src/app/account/account.module.ts | 2 -- .../middlewares/html-template.middleware.ts | 19 ++++------ apps/api/src/services/i18n/i18n.module.ts | 9 ----- apps/api/src/services/i18n/i18n.service.ts | 35 ++++++++++--------- 4 files changed, 25 insertions(+), 40 deletions(-) delete mode 100644 apps/api/src/services/i18n/i18n.module.ts diff --git a/apps/api/src/app/account/account.module.ts b/apps/api/src/app/account/account.module.ts index 213faa604..26ace47c2 100644 --- a/apps/api/src/app/account/account.module.ts +++ b/apps/api/src/app/account/account.module.ts @@ -11,7 +11,6 @@ import { Module } from '@nestjs/common'; import { AccountController } from './account.controller'; import { AccountService } from './account.service'; -import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; @Module({ controllers: [AccountController], @@ -22,7 +21,6 @@ import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; DataProviderModule, ExchangeRateDataModule, ImpersonationModule, - I18nModule, PortfolioModule, PrismaModule, RedisCacheModule, diff --git a/apps/api/src/middlewares/html-template.middleware.ts b/apps/api/src/middlewares/html-template.middleware.ts index 9d44bdbe0..bfcef2855 100644 --- a/apps/api/src/middlewares/html-template.middleware.ts +++ b/apps/api/src/middlewares/html-template.middleware.ts @@ -2,6 +2,7 @@ import * as fs from 'fs'; import { join } from 'path'; import { environment } from '@ghostfolio/api/environments/environment'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { DEFAULT_LANGUAGE_CODE, DEFAULT_ROOT_URL, @@ -11,20 +12,11 @@ import { DATE_FORMAT, interpolate } from '@ghostfolio/common/helper'; import { format } from 'date-fns'; import { NextFunction, Request, Response } from 'express'; -const descriptions = { - de: 'Mit dem Finanz-Dashboard Ghostfolio können Sie Ihr Vermögen in Form von Aktien, ETFs oder Kryptowährungen verteilt über mehrere Finanzinstitute überwachen.', - en: 'Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies across multiple platforms.', - es: 'Ghostfolio es un dashboard de finanzas personales para hacer un seguimiento de tus activos como acciones, ETFs o criptodivisas a través de múltiples plataformas.', - fr: 'Ghostfolio est un dashboard de finances personnelles qui permet de suivre vos actifs comme les actions, les ETF ou les crypto-monnaies sur plusieurs plateformes.', - it: 'Ghostfolio è un dashboard di finanza personale per tenere traccia delle vostre attività come azioni, ETF o criptovalute su più piattaforme.', - nl: 'Ghostfolio is een persoonlijk financieel dashboard om uw activa zoals aandelen, ETF’s of cryptocurrencies over meerdere platforms bij te houden.', - pt: 'Ghostfolio é um dashboard de finanças pessoais para acompanhar os seus activos como acções, ETFs ou criptomoedas em múltiplas plataformas.', - tr: 'Ghostfolio, hisse senetleri, ETF’ler veya kripto para birimleri gibi varlıklarınızı birden fazla platformda takip etmenizi sağlayan bir kişisel finans panosudur.' -}; - const title = 'Ghostfolio – Open Source Wealth Management Software'; const titleShort = 'Ghostfolio'; +const i18nService = new I18nService(); + let indexHtmlMap: { [languageCode: string]: string } = {}; try { @@ -130,7 +122,10 @@ export const HtmlTemplateMiddleware = async ( languageCode, path, rootUrl, - description: descriptions[languageCode], + description: i18nService.getTranslation({ + id: 'metaDescription', + locale: languageCode + }), featureGraphicPath: locales[path]?.featureGraphicPath ?? 'assets/cover.png', title: locales[path]?.title ?? title diff --git a/apps/api/src/services/i18n/i18n.module.ts b/apps/api/src/services/i18n/i18n.module.ts deleted file mode 100644 index b95962b39..000000000 --- a/apps/api/src/services/i18n/i18n.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { I18nService } from './i18n.service'; - -@Module({ - providers: [I18nService], - exports: [I18nService] -}) -export class I18nModule {} diff --git a/apps/api/src/services/i18n/i18n.service.ts b/apps/api/src/services/i18n/i18n.service.ts index e3326355e..962ab3a1f 100644 --- a/apps/api/src/services/i18n/i18n.service.ts +++ b/apps/api/src/services/i18n/i18n.service.ts @@ -1,12 +1,12 @@ -import { readdirSync, readFileSync, existsSync } from 'fs'; +import { readFileSync, readdirSync } from 'fs'; import { join } from 'path'; -import { Injectable, Logger } from '@nestjs/common'; + +import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; +import { Logger } from '@nestjs/common'; import * as cheerio from 'cheerio'; -@Injectable() export class I18nService { private localesPath = join(__dirname, 'assets', 'locales'); - private localeRegex = /^messages\.[a-z]{2}\.xlf$/; private translations: { [locale: string]: cheerio.CheerioAPI } = {}; public constructor() { @@ -21,15 +21,15 @@ export class I18nService { locale: string; }): string { const $ = this.translations[locale]; + if (!$) { - throw new Error(`Translation not found for locale '${locale}'`); + Logger.warn(`Translation not found for locale '${locale}'`); } const translatedText = $(`trans-unit[id="${id}"] > target`).text(); + if (!translatedText) { - throw new Error( - `Translation not found for id '${id}' in locale '${locale}'` - ); + Logger.warn(`Translation not found for id '${id}' in locale '${locale}'`); } return translatedText; @@ -38,22 +38,23 @@ export class I18nService { private loadFiles() { try { const files = readdirSync(this.localesPath, 'utf-8'); + for (const file of files) { - if (!this.localeRegex.test(file)) { - continue; - } - if (!existsSync(join(this.localesPath, file))) { - throw new Error(`File: ${file} not found`); - } else { - const xmlData = readFileSync(join(this.localesPath, file), 'utf8'); - this.translations[file.split('.')[1]] = this.parseXml(xmlData); - } + const xmlData = readFileSync(join(this.localesPath, file), 'utf8'); + this.translations[this.parseLanguageCode(file)] = + this.parseXml(xmlData); } } catch (error) { Logger.error(error, 'I18nService'); } } + private parseLanguageCode(aFileName: string) { + const match = aFileName.match(/\.([a-zA-Z]+)\.xlf$/); + + return match ? match[1] : DEFAULT_LANGUAGE_CODE; + } + private parseXml(xmlData: string): cheerio.CheerioAPI { return cheerio.load(xmlData, { xmlMode: true }); }