From 7c4cf2ca0c828cfd3a8245c659dfd65f52a49fe2 Mon Sep 17 00:00:00 2001 From: rohit <90490761+rohitsx@users.noreply.github.com> Date: Mon, 21 Jul 2025 23:55:56 +0530 Subject: [PATCH] Feature/set up language localization for Regional Market Cluster Risks (#5145) * Set up language localization for Regional Market Cluster Risks * Update changelog --- CHANGELOG.md | 8 +++ .../src/app/portfolio/portfolio.service.ts | 10 +++ apps/api/src/app/user/user.service.ts | 10 +++ .../asia-pacific.ts | 45 ++++++++---- .../emerging-markets.ts | 45 ++++++++---- .../regional-market-cluster-risk/europe.ts | 45 ++++++++---- .../regional-market-cluster-risk/japan.ts | 45 ++++++++---- .../north-america.ts | 45 ++++++++---- apps/client/src/app/pages/i18n/i18n-page.html | 72 +++++++++++++++++++ 9 files changed, 265 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bfde16b5..3d74b2482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ 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: _Regional Market Cluster Risks_ (Asia-Pacific) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (Emerging Markets) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (Europe) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (Japan) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (North America) + ### Changed - Improved the language localization for Catalan (`ca`) diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 4d09edf8b..88d6e7d60 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1272,26 +1272,36 @@ export class PortfolioService { [ new RegionalMarketClusterRiskAsiaPacific( this.exchangeRateDataService, + this.i18nService, + userSettings.language, marketsAdvancedTotalInBaseCurrency, marketsAdvanced.asiaPacific.valueInBaseCurrency ), new RegionalMarketClusterRiskEmergingMarkets( this.exchangeRateDataService, + this.i18nService, + userSettings.language, marketsAdvancedTotalInBaseCurrency, marketsAdvanced.emergingMarkets.valueInBaseCurrency ), new RegionalMarketClusterRiskEurope( this.exchangeRateDataService, + this.i18nService, + userSettings.language, marketsAdvancedTotalInBaseCurrency, marketsAdvanced.europe.valueInBaseCurrency ), new RegionalMarketClusterRiskJapan( this.exchangeRateDataService, + this.i18nService, + userSettings.language, marketsAdvancedTotalInBaseCurrency, marketsAdvanced.japan.valueInBaseCurrency ), new RegionalMarketClusterRiskNorthAmerica( this.exchangeRateDataService, + this.i18nService, + userSettings.language, marketsAdvancedTotalInBaseCurrency, marketsAdvanced.northAmerica.valueInBaseCurrency ) diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index a69167b3b..a043761fa 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -329,28 +329,38 @@ export class UserService { ).getSettings(user.settings.settings), RegionalMarketClusterRiskAsiaPacific: new RegionalMarketClusterRiskAsiaPacific( + undefined, + undefined, undefined, undefined, undefined ).getSettings(user.settings.settings), RegionalMarketClusterRiskEmergingMarkets: new RegionalMarketClusterRiskEmergingMarkets( + undefined, + undefined, undefined, undefined, undefined ).getSettings(user.settings.settings), RegionalMarketClusterRiskEurope: new RegionalMarketClusterRiskEurope( + undefined, + undefined, undefined, undefined, undefined ).getSettings(user.settings.settings), RegionalMarketClusterRiskJapan: new RegionalMarketClusterRiskJapan( + undefined, + undefined, undefined, undefined, undefined ).getSettings(user.settings.settings), RegionalMarketClusterRiskNorthAmerica: new RegionalMarketClusterRiskNorthAmerica( + undefined, + undefined, undefined, undefined, undefined diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/asia-pacific.ts b/apps/api/src/models/rules/regional-market-cluster-risk/asia-pacific.ts index cadb2f9cd..5d6cc999a 100644 --- a/apps/api/src/models/rules/regional-market-cluster-risk/asia-pacific.ts +++ b/apps/api/src/models/rules/regional-market-cluster-risk/asia-pacific.ts @@ -1,5 +1,6 @@ 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 { UserSettings } from '@ghostfolio/common/interfaces'; import { Settings } from './interfaces/rule-settings.interface'; @@ -10,10 +11,13 @@ export class RegionalMarketClusterRiskAsiaPacific extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, currentValueInBaseCurrency: number, asiaPacificValueInBaseCurrency: number ) { super(exchangeRateDataService, { + languageCode, key: RegionalMarketClusterRiskAsiaPacific.name }); @@ -28,26 +32,40 @@ export class RegionalMarketClusterRiskAsiaPacific extends Rule { if (asiaPacificMarketValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The Asia-Pacific market contribution of your current investment (${(asiaPacificMarketValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskAsiaPacific.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (asiaPacificMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } else if (asiaPacificMarketValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The Asia-Pacific market contribution of your current investment (${(asiaPacificMarketValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskAsiaPacific.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (asiaPacificMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The Asia-Pacific market contribution of your current investment (${(asiaPacificMarketValueRatio * 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.regionalMarketClusterRiskAsiaPacific.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (asiaPacificMarketValueRatio * 100).toPrecision(3) + } + }), value: true }; } @@ -70,7 +88,10 @@ export class RegionalMarketClusterRiskAsiaPacific extends Rule { } public getName() { - return 'Asia-Pacific'; + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskAsiaPacific', + languageCode: this.getLanguageCode() + }); } public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts b/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts index 5c582834c..fa13a9e57 100644 --- a/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts +++ b/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts @@ -1,5 +1,6 @@ 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 { UserSettings } from '@ghostfolio/common/interfaces'; import { Settings } from './interfaces/rule-settings.interface'; @@ -10,10 +11,13 @@ export class RegionalMarketClusterRiskEmergingMarkets extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, currentValueInBaseCurrency: number, emergingMarketsValueInBaseCurrency: number ) { super(exchangeRateDataService, { + languageCode, key: RegionalMarketClusterRiskEmergingMarkets.name }); @@ -30,26 +34,40 @@ export class RegionalMarketClusterRiskEmergingMarkets extends Rule { if (emergingMarketsValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The Emerging Markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEmergingMarkets.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (emergingMarketsValueRatio * 100).toPrecision(3) + } + }), value: false }; } else if (emergingMarketsValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The Emerging Markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEmergingMarkets.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (emergingMarketsValueRatio * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The Emerging Markets contribution of your current investment (${(emergingMarketsValueRatio * 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.regionalMarketClusterRiskEmergingMarkets.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (emergingMarketsValueRatio * 100).toPrecision(3) + } + }), value: true }; } @@ -72,7 +90,10 @@ export class RegionalMarketClusterRiskEmergingMarkets extends Rule { } public getName() { - return 'Emerging Markets'; + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEmergingMarkets', + languageCode: this.getLanguageCode() + }); } public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts b/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts index da1781786..3bbe7af84 100644 --- a/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts +++ b/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts @@ -1,5 +1,6 @@ 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 { UserSettings } from '@ghostfolio/common/interfaces'; import { Settings } from './interfaces/rule-settings.interface'; @@ -10,10 +11,13 @@ export class RegionalMarketClusterRiskEurope extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, currentValueInBaseCurrency: number, europeValueInBaseCurrency: number ) { super(exchangeRateDataService, { + languageCode, key: RegionalMarketClusterRiskEurope.name }); @@ -28,26 +32,40 @@ export class RegionalMarketClusterRiskEurope extends Rule { if (europeMarketValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEurope.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (europeMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } else if (europeMarketValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEurope.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (europeMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 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.regionalMarketClusterRiskEurope.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (europeMarketValueRatio * 100).toPrecision(3) + } + }), value: true }; } @@ -70,7 +88,10 @@ export class RegionalMarketClusterRiskEurope extends Rule { } public getName() { - return 'Europe'; + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEurope', + languageCode: this.getLanguageCode() + }); } public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/japan.ts b/apps/api/src/models/rules/regional-market-cluster-risk/japan.ts index 915f3995b..952e14795 100644 --- a/apps/api/src/models/rules/regional-market-cluster-risk/japan.ts +++ b/apps/api/src/models/rules/regional-market-cluster-risk/japan.ts @@ -1,5 +1,6 @@ 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 { UserSettings } from '@ghostfolio/common/interfaces'; import { Settings } from './interfaces/rule-settings.interface'; @@ -10,10 +11,13 @@ export class RegionalMarketClusterRiskJapan extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, currentValueInBaseCurrency: number, japanValueInBaseCurrency: number ) { super(exchangeRateDataService, { + languageCode, key: RegionalMarketClusterRiskJapan.name }); @@ -28,26 +32,40 @@ export class RegionalMarketClusterRiskJapan extends Rule { if (japanMarketValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The Japan market contribution of your current investment (${(japanMarketValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskJapan.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (japanMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } else if (japanMarketValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The Japan market contribution of your current investment (${(japanMarketValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskJapan.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (japanMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The Japan market contribution of your current investment (${(japanMarketValueRatio * 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.regionalMarketClusterRiskJapan.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (japanMarketValueRatio * 100).toPrecision(3) + } + }), value: true }; } @@ -70,7 +88,10 @@ export class RegionalMarketClusterRiskJapan extends Rule { } public getName() { - return 'Japan'; + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskJapan', + languageCode: this.getLanguageCode() + }); } public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts b/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts index 6322708d5..f022ecff9 100644 --- a/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts +++ b/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts @@ -1,5 +1,6 @@ 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 { UserSettings } from '@ghostfolio/common/interfaces'; import { Settings } from './interfaces/rule-settings.interface'; @@ -10,10 +11,13 @@ export class RegionalMarketClusterRiskNorthAmerica extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, currentValueInBaseCurrency: number, northAmericaValueInBaseCurrency: number ) { super(exchangeRateDataService, { + languageCode, key: RegionalMarketClusterRiskNorthAmerica.name }); @@ -28,26 +32,40 @@ export class RegionalMarketClusterRiskNorthAmerica extends Rule { if (northAmericaMarketValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The North America market contribution of your current investment (${(northAmericaMarketValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskNorthAmerica.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (northAmericaMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } else if (northAmericaMarketValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The North America market contribution of your current investment (${(northAmericaMarketValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskNorthAmerica.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (northAmericaMarketValueRatio * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The North America market contribution of your current investment (${(northAmericaMarketValueRatio * 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.regionalMarketClusterRiskNorthAmerica.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (northAmericaMarketValueRatio * 100).toPrecision(3) + } + }), value: true }; } @@ -70,7 +88,10 @@ export class RegionalMarketClusterRiskNorthAmerica extends Rule { } public getName() { - return 'North America'; + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskNorthAmerica', + 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 26f0b8dbb..5db40a5b0 100644 --- a/apps/client/src/app/pages/i18n/i18n-page.html +++ b/apps/client/src/app/pages/i18n/i18n-page.html @@ -149,6 +149,78 @@
  • Regional Market Cluster Risks
  • +
  • Asia-Pacific
  • +
  • + The Asia-Pacific market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Asia-Pacific market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Asia-Pacific market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • + Emerging Markets +
  • +
  • + The Emerging Markets contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Emerging Markets contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Emerging Markets contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Europe
  • +
  • + The Europe market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Europe market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Europe market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Japan
  • +
  • + The Japan market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Japan market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Japan market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • North America
  • +
  • + The North America market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The North America market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The North America market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • Open Source Wealth Management Software