Browse Source

Implement language code

pull/4779/head
Thomas Kaul 3 months ago
parent
commit
889094233b
  1. 14
      apps/api/src/app/auth/jwt.strategy.ts
  2. 10
      apps/api/src/app/endpoints/ai/ai.controller.ts
  3. 1
      apps/api/src/app/portfolio/portfolio.service.ts
  4. 2
      apps/api/src/app/subscription/subscription.service.ts
  5. 1
      apps/api/src/app/user/user.service.ts
  6. 9
      apps/api/src/models/rule.ts
  7. 39
      apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts
  8. 3
      apps/client/src/app/components/access-table/access-table.component.ts
  9. 10
      apps/client/src/app/components/admin-settings/admin-settings.component.ts
  10. 4
      apps/client/src/app/pages/i18n/i18n-page.html

14
apps/api/src/app/auth/jwt.strategy.ts

@ -1,7 +1,11 @@
import { UserService } from '@ghostfolio/api/app/user/user.service'; import { UserService } from '@ghostfolio/api/app/user/user.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { HEADER_KEY_TIMEZONE } from '@ghostfolio/common/config'; import {
DEFAULT_CURRENCY,
DEFAULT_LANGUAGE_CODE,
HEADER_KEY_TIMEZONE
} from '@ghostfolio/common/config';
import { hasRole } from '@ghostfolio/common/permissions'; import { hasRole } from '@ghostfolio/common/permissions';
import { HttpException, Injectable } from '@nestjs/common'; import { HttpException, Injectable } from '@nestjs/common';
@ -52,6 +56,14 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
}); });
} }
if (!user.Settings.settings.baseCurrency) {
user.Settings.settings.baseCurrency = DEFAULT_CURRENCY;
}
if (!user.Settings.settings.language) {
user.Settings.settings.language = DEFAULT_LANGUAGE_CODE;
}
return user; return user;
} else { } else {
throw new HttpException( throw new HttpException(

10
apps/api/src/app/endpoints/ai/ai.controller.ts

@ -1,10 +1,6 @@
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { ApiService } from '@ghostfolio/api/services/api/api.service'; import { ApiService } from '@ghostfolio/api/services/api/api.service';
import {
DEFAULT_CURRENCY,
DEFAULT_LANGUAGE_CODE
} from '@ghostfolio/common/config';
import { AiPromptResponse } from '@ghostfolio/common/interfaces'; import { AiPromptResponse } from '@ghostfolio/common/interfaces';
import { permissions } from '@ghostfolio/common/permissions'; import { permissions } from '@ghostfolio/common/permissions';
import type { AiPromptMode, RequestWithUser } from '@ghostfolio/common/types'; import type { AiPromptMode, RequestWithUser } from '@ghostfolio/common/types';
@ -53,10 +49,8 @@ export class AiController {
filters, filters,
mode, mode,
impersonationId: undefined, impersonationId: undefined,
languageCode: languageCode: this.request.user.Settings.settings.language,
this.request.user.Settings.settings.language ?? DEFAULT_LANGUAGE_CODE, userCurrency: this.request.user.Settings.settings.baseCurrency,
userCurrency:
this.request.user.Settings.settings.baseCurrency ?? DEFAULT_CURRENCY,
userId: this.request.user.id userId: this.request.user.id
}); });

1
apps/api/src/app/portfolio/portfolio.service.ts

@ -1332,6 +1332,7 @@ export class PortfolioService {
[ [
new FeeRatioInitialInvestment( new FeeRatioInitialInvestment(
this.exchangeRateDataService, this.exchangeRateDataService,
userSettings.language,
summary.committedFunds, summary.committedFunds,
summary.fees summary.fees
) )

2
apps/api/src/app/subscription/subscription.service.ts

@ -61,7 +61,7 @@ export class SubscriptionService {
const checkoutSessionCreateParams: Stripe.Checkout.SessionCreateParams = { const checkoutSessionCreateParams: Stripe.Checkout.SessionCreateParams = {
cancel_url: `${this.configurationService.get('ROOT_URL')}/${ cancel_url: `${this.configurationService.get('ROOT_URL')}/${
user.Settings?.settings?.language ?? DEFAULT_LANGUAGE_CODE user.Settings.settings.language
}/account`, }/account`,
client_reference_id: user.id, client_reference_id: user.id,
line_items: [ line_items: [

1
apps/api/src/app/user/user.service.ts

@ -302,6 +302,7 @@ export class UserService {
undefined undefined
).getSettings(user.Settings.settings), ).getSettings(user.Settings.settings),
FeeRatioInitialInvestment: new FeeRatioInitialInvestment( FeeRatioInitialInvestment: new FeeRatioInitialInvestment(
undefined,
undefined, undefined,
undefined, undefined,
undefined undefined

9
apps/api/src/models/rule.ts

@ -1,5 +1,6 @@
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config';
import { groupBy } from '@ghostfolio/common/helper'; import { groupBy } from '@ghostfolio/common/helper';
import { import {
PortfolioPosition, PortfolioPosition,
@ -14,19 +15,23 @@ import { RuleInterface } from './interfaces/rule.interface';
export abstract class Rule<T extends RuleSettings> implements RuleInterface<T> { export abstract class Rule<T extends RuleSettings> implements RuleInterface<T> {
private key: string; private key: string;
private languageCode: string;
private name: string; private name: string;
public constructor( public constructor(
protected exchangeRateDataService: ExchangeRateDataService, protected exchangeRateDataService: ExchangeRateDataService,
{ {
key, key,
languageCode = DEFAULT_LANGUAGE_CODE,
name name
}: { }: {
key: string; key: string;
languageCode?: string; // TODO: Make mandatory
name: string; name: string;
} }
) { ) {
this.key = key; this.key = key;
this.languageCode = languageCode;
this.name = name; this.name = name;
} }
@ -34,6 +39,10 @@ export abstract class Rule<T extends RuleSettings> implements RuleInterface<T> {
return this.key; return this.key;
} }
public getLanguageCode() {
return this.languageCode;
}
public getName() { public getName() {
return this.name; return this.name;
} }

39
apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts

@ -2,7 +2,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.in
import { Rule } from '@ghostfolio/api/models/rule'; import { Rule } from '@ghostfolio/api/models/rule';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service';
import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config';
import { UserSettings } from '@ghostfolio/common/interfaces'; import { UserSettings } from '@ghostfolio/common/interfaces';
export class FeeRatioInitialInvestment extends Rule<Settings> { export class FeeRatioInitialInvestment extends Rule<Settings> {
@ -12,10 +11,12 @@ export class FeeRatioInitialInvestment extends Rule<Settings> {
public constructor( public constructor(
protected exchangeRateDataService: ExchangeRateDataService, protected exchangeRateDataService: ExchangeRateDataService,
languageCode: string,
totalInvestment: number, totalInvestment: number,
fees: number fees: number
) { ) {
super(exchangeRateDataService, { super(exchangeRateDataService, {
languageCode,
key: FeeRatioInitialInvestment.name, key: FeeRatioInitialInvestment.name,
name: 'Fee Ratio' name: 'Fee Ratio'
}); });
@ -30,32 +31,28 @@ export class FeeRatioInitialInvestment extends Rule<Settings> {
: 0; : 0;
if (feeRatio > ruleSettings.thresholdMax) { if (feeRatio > ruleSettings.thresholdMax) {
const evaluation = this.i18nService.getTranslation({
id: 'rule.fee-ratio-initial-investment.exceed',
languageCode: DEFAULT_LANGUAGE_CODE,
placeholders: {
feeRatio: (ruleSettings.thresholdMax * 100).toFixed(2),
thresholdMax: (feeRatio * 100).toPrecision(3)
}
});
return { return {
evaluation, evaluation: this.i18nService.getTranslation({
id: 'rule.feeRatioInitialInvestment.exceed',
languageCode: this.getLanguageCode(),
placeholders: {
feeRatio: (ruleSettings.thresholdMax * 100).toFixed(2),
thresholdMax: (feeRatio * 100).toPrecision(3)
}
}),
value: false value: false
}; };
} }
const evaluation = this.i18nService.getTranslation({
id: 'rule.fee-ratio-initial-investment.not-exceed',
languageCode: DEFAULT_LANGUAGE_CODE,
placeholders: {
feeRatio: (feeRatio * 100).toPrecision(3),
thresholdMax: (ruleSettings.thresholdMax * 100).toFixed(2)
}
});
return { return {
evaluation, evaluation: this.i18nService.getTranslation({
id: 'rule.feeRatioInitialInvestment.notExceed',
languageCode: this.getLanguageCode(),
placeholders: {
feeRatio: (feeRatio * 100).toPrecision(3),
thresholdMax: (ruleSettings.thresholdMax * 100).toFixed(2)
}
}),
value: true value: true
}; };
} }

3
apps/client/src/app/components/access-table/access-table.component.ts

@ -1,6 +1,5 @@
import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type';
import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service';
import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config';
import { Access, User } from '@ghostfolio/common/interfaces'; import { Access, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths'; import { paths } from '@ghostfolio/common/paths';
@ -54,7 +53,7 @@ export class AccessTableComponent implements OnChanges {
} }
public getPublicUrl(aId: string): string { public getPublicUrl(aId: string): string {
const languageCode = this.user?.settings?.language ?? DEFAULT_LANGUAGE_CODE; const languageCode = this.user.settings.language;
return `${this.baseUrl}/${languageCode}/${paths.public}/${aId}`; return `${this.baseUrl}/${languageCode}/${paths.public}/${aId}`;
} }

10
apps/client/src/app/components/admin-settings/admin-settings.component.ts

@ -3,10 +3,7 @@ import { NotificationService } from '@ghostfolio/client/core/notification/notifi
import { AdminService } from '@ghostfolio/client/services/admin.service'; import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
import { import { PROPERTY_API_KEY_GHOSTFOLIO } from '@ghostfolio/common/config';
DEFAULT_LANGUAGE_CODE,
PROPERTY_API_KEY_GHOSTFOLIO
} from '@ghostfolio/common/config';
import { getDateFormatString } from '@ghostfolio/common/helper'; import { getDateFormatString } from '@ghostfolio/common/helper';
import { import {
DataProviderGhostfolioStatusResponse, DataProviderGhostfolioStatusResponse,
@ -70,11 +67,10 @@ export class AdminSettingsComponent implements OnDestroy, OnInit {
this.user = state.user; this.user = state.user;
this.defaultDateFormat = getDateFormatString( this.defaultDateFormat = getDateFormatString(
this.user?.settings?.locale this.user.settings.locale
); );
const languageCode = const languageCode = this.user.settings.language;
this.user?.settings?.language ?? DEFAULT_LANGUAGE_CODE;
this.pricingUrl = `https://ghostfol.io/${languageCode}/${paths.pricing}`; this.pricingUrl = `https://ghostfol.io/${languageCode}/${paths.pricing}`;

4
apps/client/src/app/pages/i18n/i18n-page.html

@ -11,11 +11,11 @@
performance, portfolio, software, stock, trading, wealth, web3 performance, portfolio, software, stock, trading, wealth, web3
</li> </li>
<li i18n="@@myAccount">My Account</li> <li i18n="@@myAccount">My Account</li>
<li i18n="@@rule.fee-ratio-initial-investment.exceed"> <li i18n="@@rule.feeRatioInitialInvestment.exceed">
The fees do exceed &#123;thresholdMax&#125;% of your initial investment The fees do exceed &#123;thresholdMax&#125;% of your initial investment
(&#123;feeRatio&#125;%) (&#123;feeRatio&#125;%)
</li> </li>
<li i18n="@@rule.fee-ratio-initial-investment.not-exceed"> <li i18n="@@rule.feeRatioInitialInvestment.notExceed">
The fees do not exceed &#123;thresholdMax&#125;% of your initial The fees do not exceed &#123;thresholdMax&#125;% of your initial
investment (&#123;feeRatio&#125;%) investment (&#123;feeRatio&#125;%)
</li> </li>

Loading…
Cancel
Save