From a0c5958f8101360b8f9216a7970af71969852ada Mon Sep 17 00:00:00 2001 From: Diego Noah Date: Wed, 25 Jun 2025 09:56:28 -0600 Subject: [PATCH 1/2] Feature/improve language localization for CA 20250625 (#5028) * Improve language localization for CA * Update changelog --- CHANGELOG.md | 6 ++++++ apps/client/src/locales/messages.ca.xlf | 18 +++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92519471a..41895b842 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Improved the language localization for Catalan (`ca`) + ## 2.174.0 - 2025-06-24 ### Added diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 6914f5f80..5b4e696fc 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -4845,7 +4845,7 @@ Currency Cluster Risks - Currency Cluster Risks + Riscos del clúster de divises apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html 93 @@ -4853,7 +4853,7 @@ Account Cluster Risks - Account Cluster Risks + Riscos del clúster de comptes apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html 141 @@ -4861,7 +4861,7 @@ Pricing - Pricing + Preus apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 @@ -4873,7 +4873,7 @@ Pricing Plans - Pricing Plans + Plans de preus apps/client/src/app/pages/pricing/pricing-page.html 4 @@ -4881,7 +4881,7 @@ Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. + La nostra oferta oficial al núvol Ghostfolio Premium és la manera més senzilla de començar. A causa del temps que estalvia, aquesta serà la millor opció per a la majoria de la gent. Els ingressos s’utilitzen per cobrir els costos de la infraestructura d’allotjament i per finançar el desenvolupament en curs. apps/client/src/app/pages/pricing/pricing-page.html 6 @@ -4897,7 +4897,7 @@ For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. - For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + Per a inversors experts en tecnologia que prefereixen executar Ghostfolio a la seva pròpia infraestructura. apps/client/src/app/pages/pricing/pricing-page.html 24 @@ -4905,7 +4905,7 @@ Unlimited Transactions - Unlimited Transactions + Transaccions il·limitades apps/client/src/app/pages/pricing/pricing-page.html 31 @@ -4921,7 +4921,7 @@ Unlimited Accounts - Unlimited Accounts + Comptes il·limitats apps/client/src/app/pages/pricing/pricing-page.html 35 @@ -4937,7 +4937,7 @@ Portfolio Performance - Portfolio Performance + Rendiment de la cartera apps/client/src/app/pages/pricing/pricing-page.html 39 From a7a33eeb56faafa8e5b627b9eccc234cb10a6655 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 25 Jun 2025 18:08:45 +0200 Subject: [PATCH 2/2] Bugfix/fix locale in scraper configuration (#5011) * Fix locale in scraper configuration * Update changelog --- CHANGELOG.md | 4 +++ apps/api/src/app/admin/admin.controller.ts | 8 ++--- .../data-provider/manual/manual.service.ts | 8 +++-- .../asset-profile-dialog.component.ts | 35 ++++++++++++------- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41895b842..7636f30e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the language localization for Catalan (`ca`) +### Fixed + +- Fixed an issue with the locale in the scraper configuration + ## 2.174.0 - 2025-06-24 ### Added diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 82524ef9b..8531cf95c 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -17,7 +17,8 @@ import { AdminData, AdminMarketData, AdminUsers, - EnhancedSymbolProfile + EnhancedSymbolProfile, + ScraperConfiguration } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; import type { @@ -222,13 +223,12 @@ export class AdminController { @Post('market-data/:dataSource/:symbol/test') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async testMarketData( - @Body() data: { scraperConfiguration: string }, + @Body() data: { scraperConfiguration: ScraperConfiguration }, @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string ): Promise<{ price: number }> { try { - const scraperConfiguration = JSON.parse(data.scraperConfiguration); - const price = await this.manualService.test(scraperConfiguration); + const price = await this.manualService.test(data.scraperConfiguration); if (price) { return { price }; diff --git a/apps/api/src/services/data-provider/manual/manual.service.ts b/apps/api/src/services/data-provider/manual/manual.service.ts index 66e625e47..bcaa77a17 100644 --- a/apps/api/src/services/data-provider/manual/manual.service.ts +++ b/apps/api/src/services/data-provider/manual/manual.service.ts @@ -104,7 +104,7 @@ export class ManualService implements DataProviderInterface { } return historical; - } else if (selector === undefined || url === undefined) { + } else if (!selector || !url) { return {}; } @@ -162,7 +162,11 @@ export class ManualService implements DataProviderInterface { const symbolProfilesWithScraperConfigurationAndInstantMode = symbolProfiles.filter(({ scraperConfiguration }) => { - return scraperConfiguration?.mode === 'instant'; + return ( + scraperConfiguration?.mode === 'instant' && + scraperConfiguration?.selector && + scraperConfiguration?.url + ); }); const scraperResultPromises = diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts index d9b344699..c52d9137d 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts @@ -11,6 +11,7 @@ import { AdminMarketDataDetails, AssetProfileIdentifier, LineChartItem, + ScraperConfiguration, User } from '@ghostfolio/common/interfaces'; import { translate } from '@ghostfolio/ui/i18n'; @@ -41,6 +42,7 @@ import { AssetClass, AssetSubClass, MarketData, + Prisma, SymbolProfile } from '@prisma/client'; import { format } from 'date-fns'; @@ -343,7 +345,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit { public async onSubmitAssetProfileForm() { let countries = []; - let scraperConfiguration = {}; + let scraperConfiguration: ScraperConfiguration = { + selector: '', + url: '' + }; let sectors = []; let symbolMapping = {}; @@ -354,9 +359,9 @@ export class AssetProfileDialog implements OnDestroy, OnInit { try { scraperConfiguration = { defaultMarketPrice: - this.assetProfileForm.controls['scraperConfiguration'].controls[ + (this.assetProfileForm.controls['scraperConfiguration'].controls[ 'defaultMarketPrice' - ].value, + ].value as number) || undefined, headers: JSON.parse( this.assetProfileForm.controls['scraperConfiguration'].controls[ 'headers' @@ -365,10 +370,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit { locale: this.assetProfileForm.controls['scraperConfiguration'].controls[ 'locale' - ].value, + ].value || undefined, mode: this.assetProfileForm.controls['scraperConfiguration'].controls[ 'mode' - ].value, + ].value as ScraperConfiguration['mode'], selector: this.assetProfileForm.controls['scraperConfiguration'].controls[ 'selector' @@ -377,6 +382,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit { 'url' ].value }; + + if (!scraperConfiguration.selector || !scraperConfiguration.url) { + scraperConfiguration = undefined; + } } catch {} try { @@ -391,7 +400,6 @@ export class AssetProfileDialog implements OnDestroy, OnInit { const assetProfile: UpdateAssetProfileDto = { countries, - scraperConfiguration, sectors, symbolMapping, assetClass: this.assetProfileForm.get('assetClass').value, @@ -400,6 +408,8 @@ export class AssetProfileDialog implements OnDestroy, OnInit { currency: this.assetProfileForm.get('currency').value, isActive: this.assetProfileForm.get('isActive').value, name: this.assetProfileForm.get('name').value, + scraperConfiguration: + scraperConfiguration as unknown as Prisma.InputJsonObject, url: this.assetProfileForm.get('url').value || null }; @@ -493,11 +503,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit { this.adminService .testMarketData({ dataSource: this.data.dataSource, - scraperConfiguration: JSON.stringify({ - defaultMarketPrice: - this.assetProfileForm.controls['scraperConfiguration'].controls[ - 'defaultMarketPrice' - ].value, + scraperConfiguration: { + defaultMarketPrice: this.assetProfileForm.controls[ + 'scraperConfiguration' + ].controls['defaultMarketPrice'].value as number, headers: JSON.parse( this.assetProfileForm.controls['scraperConfiguration'].controls[ 'headers' @@ -506,7 +515,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit { locale: this.assetProfileForm.controls['scraperConfiguration'].controls[ 'locale' - ].value, + ].value || undefined, mode: this.assetProfileForm.controls['scraperConfiguration'].controls[ 'mode' ].value, @@ -517,7 +526,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit { url: this.assetProfileForm.controls['scraperConfiguration'].controls[ 'url' ].value - }), + }, symbol: this.data.symbol }) .pipe(