From b5a44bcdb901c34e3fc313d8c6fa970382ad1d14 Mon Sep 17 00:00:00 2001 From: Dhoni77 Date: Tue, 17 Oct 2023 21:39:29 +0530 Subject: [PATCH] feat: i18n service to query xml files --- apps/api/src/app/account/account.module.ts | 2 + apps/api/src/services/i18n/i18n.module.ts | 9 ++++ apps/api/src/services/i18n/i18n.service.ts | 59 ++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 apps/api/src/services/i18n/i18n.module.ts create mode 100644 apps/api/src/services/i18n/i18n.service.ts diff --git a/apps/api/src/app/account/account.module.ts b/apps/api/src/app/account/account.module.ts index 26ace47c2..213faa604 100644 --- a/apps/api/src/app/account/account.module.ts +++ b/apps/api/src/app/account/account.module.ts @@ -11,6 +11,7 @@ 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], @@ -21,6 +22,7 @@ import { AccountService } from './account.service'; DataProviderModule, ExchangeRateDataModule, ImpersonationModule, + I18nModule, PortfolioModule, PrismaModule, RedisCacheModule, diff --git a/apps/api/src/services/i18n/i18n.module.ts b/apps/api/src/services/i18n/i18n.module.ts new file mode 100644 index 000000000..b95962b39 --- /dev/null +++ b/apps/api/src/services/i18n/i18n.module.ts @@ -0,0 +1,9 @@ +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 new file mode 100644 index 000000000..b169163b6 --- /dev/null +++ b/apps/api/src/services/i18n/i18n.service.ts @@ -0,0 +1,59 @@ +import * as fs from 'fs'; +import { join } from 'path'; +import { Injectable } 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 } = {}; + + constructor() { + this.loadFiles(); + } + + public getTranslation({ + id, + locale + }: { + id: string; + locale: string; + }): string { + const $ = this.translations[locale]; + if (!$) { + throw new Error(`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}'` + ); + } + + return translatedText; + } + + private loadFiles() { + try { + const files = fs.readdirSync(this.localesPath, 'utf-8'); + for (const file of files) { + if (!this.localeRegex.test(file)) continue; + if (!fs.existsSync(`${this.localesPath}${file}`)) { + throw new Error(`File: ${file} not found`); + } else { + const xmlData = fs.readFileSync(`${this.localesPath}${file}`, 'utf8'); + this.translations[file.split('.')[1]] = this.parseXml(xmlData); + } + } + } catch (error) { + console.log(error); + } + } + + private parseXml(xmlData: string): cheerio.CheerioAPI { + const selectorFn = cheerio.load(xmlData, { xmlMode: true }); + return selectorFn; + } +}