From abe756dca6348039c19e68d4cd3907b47a848a9f Mon Sep 17 00:00:00 2001 From: tobikugel Date: Wed, 4 Jun 2025 14:17:01 -0300 Subject: [PATCH] implements singleton Injectable I18nService --- apps/api/src/app/endpoints/ai/ai.module.ts | 2 ++ .../src/app/endpoints/benchmarks/benchmarks.module.ts | 2 ++ apps/api/src/app/endpoints/public/public.module.ts | 2 ++ apps/api/src/app/portfolio/portfolio.module.ts | 2 ++ apps/api/src/app/portfolio/portfolio.service.ts | 5 ++++- apps/api/src/app/user/user.module.ts | 2 ++ apps/api/src/app/user/user.service.ts | 4 ++-- apps/api/src/models/rule.ts | 2 +- .../models/rules/fees/fee-ratio-initial-investment.ts | 3 ++- apps/api/src/services/i18n/i18n.module.ts | 9 +++++++++ apps/api/src/services/i18n/i18n.service.ts | 3 ++- 11 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 apps/api/src/services/i18n/i18n.module.ts diff --git a/apps/api/src/app/endpoints/ai/ai.module.ts b/apps/api/src/app/endpoints/ai/ai.module.ts index b6f9941ad..42480efd7 100644 --- a/apps/api/src/app/endpoints/ai/ai.module.ts +++ b/apps/api/src/app/endpoints/ai/ai.module.ts @@ -12,6 +12,7 @@ import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.mo import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; @@ -32,6 +33,7 @@ import { AiService } from './ai.service'; ConfigurationModule, DataProviderModule, ExchangeRateDataModule, + I18nModule, ImpersonationModule, MarketDataModule, OrderModule, diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts index a0f443621..dc651667e 100644 --- a/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts @@ -15,6 +15,7 @@ import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.s import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; @@ -36,6 +37,7 @@ import { BenchmarksService } from './benchmarks.service'; DataProviderModule, ExchangeRateDataModule, ImpersonationModule, + I18nModule, MarketDataModule, OrderModule, PortfolioSnapshotQueueModule, diff --git a/apps/api/src/app/endpoints/public/public.module.ts b/apps/api/src/app/endpoints/public/public.module.ts index cf4fd3d18..19e281dde 100644 --- a/apps/api/src/app/endpoints/public/public.module.ts +++ b/apps/api/src/app/endpoints/public/public.module.ts @@ -12,6 +12,7 @@ import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -29,6 +30,7 @@ import { PublicController } from './public.controller'; BenchmarkModule, DataProviderModule, ExchangeRateDataModule, + I18nModule, ImpersonationModule, MarketDataModule, OrderModule, diff --git a/apps/api/src/app/portfolio/portfolio.module.ts b/apps/api/src/app/portfolio/portfolio.module.ts index 0f64b2f6a..5a541f36d 100644 --- a/apps/api/src/app/portfolio/portfolio.module.ts +++ b/apps/api/src/app/portfolio/portfolio.module.ts @@ -13,6 +13,7 @@ import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.mo import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -40,6 +41,7 @@ import { RulesService } from './rules.service'; DataProviderModule, ExchangeRateDataModule, ImpersonationModule, + I18nModule, MarketDataModule, OrderModule, PerformanceLoggingModule, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index eb6abc224..d463a3e40 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -23,6 +23,7 @@ import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/ru import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { @@ -106,6 +107,7 @@ export class PortfolioService { private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly impersonationService: ImpersonationService, + private readonly i18nService: I18nService, private readonly orderService: OrderService, @Inject(REQUEST) private readonly request: RequestWithUser, private readonly rulesService: RulesService, @@ -1335,7 +1337,8 @@ export class PortfolioService { this.exchangeRateDataService, userSettings.language, summary.committedFunds, - summary.fees + summary.fees, + this.i18nService ) ], userSettings diff --git a/apps/api/src/app/user/user.module.ts b/apps/api/src/app/user/user.module.ts index 063cfef82..8a21b0a55 100644 --- a/apps/api/src/app/user/user.module.ts +++ b/apps/api/src/app/user/user.module.ts @@ -1,6 +1,7 @@ import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; import { TagModule } from '@ghostfolio/api/services/tag/tag.module'; @@ -16,6 +17,7 @@ import { UserService } from './user.service'; exports: [UserService], imports: [ ConfigurationModule, + I18nModule, JwtModule.register({ secret: process.env.JWT_SECRET_KEY, signOptions: { expiresIn: '30 days' } diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 21790182f..14d7ea79a 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -52,11 +52,10 @@ import { sortBy, without } from 'lodash'; @Injectable() export class UserService { - private i18nService = new I18nService(); - public constructor( private readonly configurationService: ConfigurationService, private readonly eventEmitter: EventEmitter2, + private readonly i18nService: I18nService, private readonly orderService: OrderService, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, @@ -306,6 +305,7 @@ export class UserService { undefined, undefined, undefined, + undefined, undefined ).getSettings(user.Settings.settings), RegionalMarketClusterRiskAsiaPacific: diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts index 0870be03e..d0c3283cf 100644 --- a/apps/api/src/models/rule.ts +++ b/apps/api/src/models/rule.ts @@ -57,7 +57,7 @@ export abstract class Rule implements RuleInterface { previousValue + this.exchangeRateDataService.toCurrency( new Big(currentValue.quantity) - .mul(currentValue.marketPrice) + .mul(currentValue.marketPrice ?? 0) .toNumber(), currentValue.currency, baseCurrency diff --git a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts index 4298eed44..99afe5e40 100644 --- a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts +++ b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts @@ -13,7 +13,8 @@ export class FeeRatioInitialInvestment extends Rule { protected exchangeRateDataService: ExchangeRateDataService, languageCode: string, totalInvestment: number, - fees: number + fees: number, + private i18nService: I18nService ) { super(exchangeRateDataService, { languageCode, 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 index 533abf2e2..a0389ab36 100644 --- a/apps/api/src/services/i18n/i18n.service.ts +++ b/apps/api/src/services/i18n/i18n.service.ts @@ -1,10 +1,11 @@ import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; -import { Logger } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as cheerio from 'cheerio'; import { readFileSync, readdirSync } from 'fs'; import { join } from 'path'; +@Injectable() export class I18nService { private localesPath = join(__dirname, 'assets', 'locales'); private translations: { [locale: string]: cheerio.CheerioAPI } = {};