diff --git a/CHANGELOG.md b/CHANGELOG.md index 159f20c24..72595e388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Set up the language localization for the static portfolio analysis rule: _Asset Class Cluster Risks_ (Equity) +- Set up the language localization for the static portfolio analysis rule: _Asset Class Cluster Risks_ (Fixed Income) + ### Changed - Changed `node main` to `exec node main` in the `entrypoint.sh` file to improve the container signal handling diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index aed8e0acb..6a580f42f 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1280,10 +1280,14 @@ export class PortfolioService { [ new AssetClassClusterRiskEquity( this.exchangeRateDataService, + this.i18nService, + userSettings.language, Object.values(holdings) ), new AssetClassClusterRiskFixedIncome( this.exchangeRateDataService, + this.i18nService, + userSettings.language, Object.values(holdings) ) ], diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 46b46bce2..161d490d7 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -272,10 +272,14 @@ export class UserService { {} ).getSettings(user.Settings.settings), AssetClassClusterRiskEquity: new AssetClassClusterRiskEquity( + undefined, + undefined, undefined, undefined ).getSettings(user.Settings.settings), AssetClassClusterRiskFixedIncome: new AssetClassClusterRiskFixedIncome( + undefined, + undefined, undefined, undefined ).getSettings(user.Settings.settings), diff --git a/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts b/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts index b386f3e18..704cfdb85 100644 --- a/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts +++ b/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PortfolioPosition, UserSettings } from '@ghostfolio/common/interfaces'; export class AssetClassClusterRiskEquity extends Rule { @@ -8,9 +9,12 @@ export class AssetClassClusterRiskEquity extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, holdings: PortfolioPosition[] ) { super(exchangeRateDataService, { + languageCode, key: AssetClassClusterRiskEquity.name }); @@ -40,26 +44,39 @@ export class AssetClassClusterRiskEquity extends Rule { if (equityValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The equity contribution of your current investment (${(equityValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + equityValueRatio: (equityValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: false }; } else if (equityValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The equity contribution of your current investment (${(equityValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + equityValueRatio: (equityValueRatio * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: false }; } - return { - evaluation: `The equity contribution of your current investment (${(equityValueRatio * 100).toPrecision(3)}%) is within the range of ${( - ruleSettings.thresholdMin * 100 - ).toPrecision( - 3 - )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity.true', + languageCode: this.getLanguageCode(), + placeholders: { + equityValueRatio: (equityValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: true }; } @@ -78,7 +95,10 @@ export class AssetClassClusterRiskEquity extends Rule { } public getName() { - return 'Equity'; + return this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity', + languageCode: this.getLanguageCode() + }); } public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { diff --git a/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts b/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts index 918856c45..e0ca92311 100644 --- a/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts +++ b/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PortfolioPosition, UserSettings } from '@ghostfolio/common/interfaces'; export class AssetClassClusterRiskFixedIncome extends Rule { @@ -8,9 +9,12 @@ export class AssetClassClusterRiskFixedIncome extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, holdings: PortfolioPosition[] ) { super(exchangeRateDataService, { + languageCode, key: AssetClassClusterRiskFixedIncome.name }); @@ -40,26 +44,39 @@ export class AssetClassClusterRiskFixedIncome extends Rule { if (fixedIncomeValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The fixed income contribution of your current investment (${(fixedIncomeValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + fixedIncomeValueRatio: (fixedIncomeValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: false }; } else if (fixedIncomeValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The fixed income contribution of your current investment (${(fixedIncomeValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + fixedIncomeValueRatio: (fixedIncomeValueRatio * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: false }; } - return { - evaluation: `The fixed income contribution of your current investment (${(fixedIncomeValueRatio * 100).toPrecision(3)}%) is within the range of ${( - ruleSettings.thresholdMin * 100 - ).toPrecision( - 3 - )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome.true', + languageCode: this.getLanguageCode(), + placeholders: { + fixedIncomeValueRatio: (fixedIncomeValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: true }; } @@ -78,7 +95,10 @@ export class AssetClassClusterRiskFixedIncome extends Rule { } public getName() { - return 'Fixed Income'; + return this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome', + languageCode: this.getLanguageCode() + }); } public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { diff --git a/apps/client/src/app/pages/i18n/i18n-page.html b/apps/client/src/app/pages/i18n/i18n-page.html index 20fa23f9a..6ffd5b011 100644 --- a/apps/client/src/app/pages/i18n/i18n-page.html +++ b/apps/client/src/app/pages/i18n/i18n-page.html @@ -28,6 +28,35 @@
  • Your net worth is managed by ${accountsLength} accounts
  • +
  • Equity
  • +
  • + The equity contribution of your current investment + (${equityValueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The equity contribution of your current investment + (${equityValueRatio}%) is below ${thresholdMin}% +
  • +
  • + The equity contribution of your current investment + (${equityValueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Fixed Income
  • +
  • + The fixed income contribution of your current investment + (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The fixed income contribution of your current investment + (${fixedIncomeValueRatio}%) is below + ${thresholdMin}% +
  • +
  • + The fixed income contribution of your current investment + (${fixedIncomeValueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • Emergency Fund: Set up
  • No emergency fund has been set up