From 1822a09c6a97982a2eb045b3a00e117332f9991a Mon Sep 17 00:00:00 2001
From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com>
Date: Sun, 2 Aug 2026 02:40:26 +0700
Subject: [PATCH 1/3] Task/improve language localization for ZH (20260731)
(#7490)
* Update translations
* Update changelog
---
CHANGELOG.md | 6 +
apps/client/src/locales/messages.zh.xlf | 152 ++++++++++++------------
2 files changed, 82 insertions(+), 76 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b31046e8cd..cf5ab1a700 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 Chinese (`zh`)
+
## 3.39.0 - 2026-08-01
### Changed
diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf
index a70be75d61..7963e7767f 100644
--- a/apps/client/src/locales/messages.zh.xlf
+++ b/apps/client/src/locales/messages.zh.xlf
@@ -433,7 +433,7 @@
Copy
- Copy
+ 复制
libs/ui/src/lib/notifications/alert-dialog/alert-dialog.html
20
@@ -605,7 +605,7 @@
Paid
- Paid
+ 付费
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts
129
@@ -657,7 +657,7 @@
Unknown
- Unknown
+ 未知
libs/ui/src/lib/i18n.ts
88
@@ -701,7 +701,7 @@
and is driven by the efforts of its contributors
- 并且得益于其 贡献者
+ 并且得益于其 贡献者
apps/client/src/app/pages/about/overview/about-overview-page.html
50
@@ -749,7 +749,7 @@
Find an account...
- Find an account...
+ 查找账户...
libs/ui/src/lib/assistant/assistant.component.ts
448
@@ -777,7 +777,7 @@
Watch the Ghostfol.io Trailer on YouTube
- Watch the Ghostfol.io Trailer on YouTube
+ 在 YouTube 上观看 Ghostfol.io 预告片
apps/client/src/app/pages/landing/landing-page.html
19
@@ -813,7 +813,7 @@
Category
- Category
+ 类别
apps/client/src/app/pages/resources/personal-finance-tools/product-page.html
77
@@ -837,7 +837,7 @@
An error occurred while converting the data source to .
- An error occurred while converting the data source to .
+ 将数据源转换为 时发生错误。
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
482
@@ -885,7 +885,7 @@
Data Gathering Frequency
- Data Gathering Frequency
+ 数据采集频率
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
468
@@ -921,7 +921,7 @@
Apply current market price
- Apply current market price
+ 应用当前市场价格
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
238
@@ -929,7 +929,7 @@
Subscription History
- Subscription History
+ 订阅历史
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html
141
@@ -965,7 +965,7 @@
Healthcare
- Healthcare
+ 医疗保健
libs/ui/src/lib/i18n.ts
97
@@ -1081,7 +1081,7 @@
Update Activity
- Update Activity
+ 更新活动
libs/common/src/lib/routes/routes.ts
141
@@ -1089,7 +1089,7 @@
Technology
- Technology
+ 科技
libs/ui/src/lib/i18n.ts
101
@@ -1105,7 +1105,7 @@
Total
- Total
+ 总计
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html
160
@@ -1161,7 +1161,7 @@
Industrials
- Industrials
+ 工业
libs/ui/src/lib/i18n.ts
98
@@ -1197,7 +1197,7 @@
Consumer Cyclical
- Consumer Cyclical
+ 非必需消费品
libs/ui/src/lib/i18n.ts
93
@@ -1705,7 +1705,7 @@
The source code is fully available as open source software (OSS) under the AGPL-3.0 license
- 源代码完全可用,作为开源软件 (OSS),遵循AGPL-3.0许可证
+ 源代码完全可用,作为开源软件 (OSS),遵循AGPL-3.0许可证
apps/client/src/app/pages/about/overview/about-overview-page.html
16
@@ -1889,7 +1889,7 @@
Energy
- Energy
+ 能源
libs/ui/src/lib/i18n.ts
95
@@ -2265,7 +2265,7 @@
Ghostfolio in Numbers: Monthly Active Users (MAU)
- Ghostfolio in Numbers: Monthly Active Users (MAU)
+ Ghostfolio 数据:月活跃用户数 (MAU)
apps/client/src/app/pages/landing/landing-page.html
63
@@ -2305,7 +2305,7 @@
The value has been copied to the clipboard
- The value has been copied to the clipboard
+ 该值已复制到剪贴板
libs/ui/src/lib/notifications/alert-dialog/alert-dialog.component.ts
46
@@ -2357,7 +2357,7 @@
Consumer Defensive
- Consumer Defensive
+ 必需消费品
libs/ui/src/lib/i18n.ts
94
@@ -2429,7 +2429,7 @@
Utilities
- Utilities
+ 公用事业
libs/ui/src/lib/i18n.ts
102
@@ -2461,7 +2461,7 @@
Coupon
- Coupon
+ 优惠券
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts
134
@@ -2497,7 +2497,7 @@
Close Account
- Close Account
+ 关闭账户
apps/client/src/app/components/user-account-settings/user-account-settings.html
337
@@ -2517,7 +2517,7 @@
Contributors to Ghostfolio
- Contributors to Ghostfolio
+ Ghostfolio 贡献者
apps/client/src/app/pages/about/overview/about-overview-page.html
54
@@ -2561,7 +2561,7 @@
Investments
- Investments
+ 投资
apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html
197
@@ -2853,7 +2853,7 @@
Financial Planning
- Financial Planning
+ 财务规划
libs/ui/src/lib/i18n.ts
109
@@ -3121,7 +3121,7 @@
popular
- popular
+ 热门
apps/client/src/app/components/admin-settings/admin-settings.component.html
79
@@ -3157,7 +3157,7 @@
Invalid API key
- Invalid API key
+ 无效的 API 密钥
apps/client/src/app/components/admin-settings/admin-settings.component.html
112
@@ -3201,7 +3201,7 @@
For security reasons, please delete all activities and accounts first before your Ghostfolio account can be closed.
- For security reasons, please delete all activities and accounts first before your Ghostfolio account can be closed.
+ 出于安全原因,在关闭您的 Ghostfolio 账户之前,请先删除所有活动和账户。
apps/client/src/app/components/user-account-settings/user-account-settings.html
348
@@ -3329,7 +3329,7 @@
Creation
- Creation
+ 创建时间
apps/client/src/app/components/admin-overview/admin-overview.html
185
@@ -3373,7 +3373,7 @@
just now
- just now
+ 刚刚
apps/client/src/app/components/admin-users/admin-users.component.ts
221
@@ -3561,7 +3561,7 @@
Basic Materials
- Basic Materials
+ 基础材料
libs/ui/src/lib/i18n.ts
91
@@ -3705,7 +3705,7 @@
Oops! Could not delete the asset profiles.
- Oops! Could not delete the asset profiles.
+ 哎呀!无法删除资产概况。
apps/client/src/app/components/admin-market-data/admin-market-data.service.ts
52
@@ -3777,7 +3777,7 @@
Add Activity
- Add Activity
+ 添加活动
libs/common/src/lib/routes/routes.ts
134
@@ -3801,7 +3801,7 @@
At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status.
- 在 Ghostfolio,透明度是我们价值观的核心。我们将源代码发布为开源软件(OSS)下AGPL-3.0许可证我们公开分享平台运营状态的汇总关键指标。
+ 在 Ghostfolio,透明度是我们价值观的核心。我们将源代码发布为开源软件(OSS)下AGPL-3.0许可证我们公开分享平台运营状态的汇总关键指标。
apps/client/src/app/pages/open/open-page.html
7
@@ -3845,7 +3845,7 @@
Convert to
- Convert to
+ 转换为
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
175
@@ -3897,7 +3897,7 @@
Available on
- Available on
+ 适用于
apps/client/src/app/pages/resources/personal-finance-tools/product-page.html
130
@@ -4197,7 +4197,7 @@
Price
- Price
+ 价格
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html
176
@@ -4205,7 +4205,7 @@
Do you really want to convert this asset profile to ()?
- Do you really want to convert this asset profile to ()?
+ 您确定要把此资产概况转换为 () 吗?
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
723
@@ -4305,7 +4305,7 @@
Trial
- Trial
+ 试用
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts
133
@@ -4605,7 +4605,7 @@
Hourly
- Hourly
+ 每小时
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
216
@@ -4717,7 +4717,7 @@
Expiration
- Expiration
+ 到期时间
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html
209
@@ -4970,7 +4970,7 @@
Coupon has been created
- Coupon has been created
+ 优惠券 已创建
apps/client/src/app/components/admin-overview/admin-overview.component.ts
224
@@ -5022,7 +5022,7 @@
Upgrade to Ghostfolio Premium
- Upgrade to Ghostfolio Premium
+ 升级至 Ghostfolio Premium
libs/ui/src/lib/premium-indicator/premium-indicator.component.html
4
@@ -5110,7 +5110,7 @@
Stock Tracking
- Stock Tracking
+ 股票追踪
libs/ui/src/lib/i18n.ts
112
@@ -5134,7 +5134,7 @@
Web
- Web
+ 网页
libs/ui/src/lib/i18n.ts
121
@@ -5334,7 +5334,7 @@
Portfolio Filters
- Portfolio Filters
+ 组合筛选器
apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html
63
@@ -5390,7 +5390,7 @@
{VAR_PLURAL, plural, =1 {Profile} other {Profiles}}
- {VAR_PLURAL, plural, =1 {Profile} other {Profiles}}
+ {VAR_PLURAL, plural, =1 {个资产概况} other {个资产概况}}
apps/client/src/app/components/admin-market-data/admin-market-data.html
275
@@ -5710,7 +5710,7 @@
Ghostfolio in Numbers: Pulls on Docker Hub
- Ghostfolio in Numbers: Pulls on Docker Hub
+ Ghostfolio 数据:Docker Hub 下载量
apps/client/src/app/pages/landing/landing-page.html
101
@@ -6022,7 +6022,7 @@
Communication Services
- Communication Services
+ 通信服务
libs/ui/src/lib/i18n.ts
92
@@ -6062,7 +6062,7 @@
Invested Capital
- Invested Capital
+ 投入资本
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
174
@@ -6346,7 +6346,7 @@
Expires ()
- Expires ()
+ 到期时间 ()
apps/client/src/app/components/admin-users/admin-users.html
34
@@ -6386,7 +6386,7 @@
Fetch market price
- Fetch market price
+ 获取市场价格
libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html
40
@@ -6479,7 +6479,7 @@
Find a holding...
- Find a holding...
+ 查找持仓...
libs/ui/src/lib/assistant/assistant.component.ts
449
@@ -6507,7 +6507,7 @@
Daily
- Daily
+ 每天
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
212
@@ -6639,7 +6639,7 @@
Jump to a page...
- Jump to a page...
+ 跳转到页面...
libs/ui/src/lib/assistant/assistant.component.ts
450
@@ -6687,7 +6687,7 @@
Clone Activity
- Clone Activity
+ 克隆活动
libs/common/src/lib/routes/routes.ts
129
@@ -6835,7 +6835,7 @@
Oops! Could not delete the asset profile.
- Oops! Could not delete the asset profile.
+ 哎呀!无法删除资产概况。
apps/client/src/app/components/admin-market-data/admin-market-data.service.ts
51
@@ -6939,7 +6939,7 @@
Do you really want to delete these asset profiles?
- Do you really want to delete these asset profiles?
+ 您确定要删除这 个资产概况吗?
apps/client/src/app/components/admin-market-data/admin-market-data.service.ts
67
@@ -7119,7 +7119,7 @@
Tax Reporting
- Tax Reporting
+ 税务报告
libs/ui/src/lib/i18n.ts
113
@@ -7135,7 +7135,7 @@
Change with currency effect Change
- 含货币影响的涨跌 涨跌
+ 含货币影响的涨跌 涨跌
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
64
@@ -7151,7 +7151,7 @@
Performance with currency effect Performance
- 含货币影响的表现 表现
+ 含货币影响的表现 表现
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
84
@@ -7199,7 +7199,7 @@
has been copied to the clipboard
- 已复制到剪贴板
+ 已复制到剪贴板
apps/client/src/app/components/admin-overview/admin-overview.component.ts
223
@@ -7219,7 +7219,7 @@
Compare Ghostfolio to -
- Compare Ghostfolio to -
+ 对比 Ghostfolio 与 -
apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html
32
@@ -7267,7 +7267,7 @@
Financial Services
- Financial Services
+ 金融服务
libs/ui/src/lib/i18n.ts
96
@@ -7295,7 +7295,7 @@
Delete
- Delete
+ 删除
apps/client/src/app/components/admin-market-data/admin-market-data.html
270
@@ -7355,7 +7355,7 @@
Dividend Tracking
- Dividend Tracking
+ 股息追踪
libs/ui/src/lib/i18n.ts
106
@@ -7415,7 +7415,7 @@
Investment Research
- Investment Research
+ 投资研究
libs/ui/src/lib/i18n.ts
110
@@ -7697,7 +7697,7 @@
Net Worth Tracking
- Net Worth Tracking
+ 净资产追踪
libs/ui/src/lib/i18n.ts
111
@@ -7769,7 +7769,7 @@
Do you really want to convert the data source to ?
- Do you really want to convert the data source to ?
+ 您确定要把数据源转换为 吗?
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
485
@@ -7837,7 +7837,7 @@
Ghostfolio in Numbers: Stars on GitHub
- Ghostfolio in Numbers: Stars on GitHub
+ Ghostfolio 数据:GitHub Stars 数量
apps/client/src/app/pages/landing/landing-page.html
82
@@ -8167,7 +8167,7 @@
ETF Tracking
- ETF Tracking
+ ETF 追踪
libs/ui/src/lib/i18n.ts
107
@@ -8333,7 +8333,7 @@
Post to Ghostfolio on X (formerly Twitter)
- Post to Ghostfolio on X (formerly Twitter)
+ 在 X (前身为 Twitter) 上发布给 Ghostfolio
apps/client/src/app/pages/about/overview/about-overview-page.html
85
@@ -8570,7 +8570,7 @@
If you encounter a bug, would like to suggest an improvement or a new feature, please join the Ghostfolio Slack community, post to @ghostfolio_
- 如果您遇到错误,想要建议改进或新功能,请加入 Ghostfolio Slack 社区,发布到 @ghostfolio_
+ 如果您遇到错误,想要建议改进或新功能,请加入 Ghostfolio Slack 社区,发布到 @ghostfolio_
apps/client/src/app/pages/about/overview/about-overview-page.html
71
From c3e70091aee0f08389e4ab5a23425839a9a79379 Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Sat, 1 Aug 2026 23:01:38 +0200
Subject: [PATCH 2/3] Bugfix/validation error caused by empty strings in asset
profile details dialog (#7509)
* Resolve validation error caused by empty strings
* Update changelog
---
CHANGELOG.md | 4 ++
.../asset-profile-dialog.component.ts | 16 +++--
.../src/lib/dtos/update-asset-profile.dto.ts | 4 +-
libs/common/src/lib/helper.spec.ts | 58 +++++++++++++++++++
libs/common/src/lib/helper.ts | 20 +++++++
5 files changed, 94 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf5ab1a700..054a24bdf3 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 Chinese (`zh`)
+### Fixed
+
+- Resolved a validation error caused by empty strings in the asset profile details dialog of the admin control panel
+
## 3.39.0 - 2026-08-01
### Changed
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 c5562740fd..330688da18 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,8 @@ import {
DATE_FORMAT,
getCountryName,
getCurrencyFromSymbol,
+ getStringOrNull,
+ getStringOrUndefined,
isCurrency
} from '@ghostfolio/common/helper';
import {
@@ -568,9 +570,10 @@ export class GfAssetProfileDialogComponent implements OnInit {
this.assetProfileForm.controls.scraperConfiguration.controls.headers
.value ?? '{}'
) as Record,
- locale:
+ locale: getStringOrUndefined(
this.assetProfileForm.controls.scraperConfiguration.controls.locale
- ?.value ?? undefined,
+ ?.value
+ ),
mode:
this.assetProfileForm.controls.scraperConfiguration.controls.mode
?.value ?? undefined,
@@ -619,7 +622,7 @@ export class GfAssetProfileDialogComponent implements OnInit {
assetClass: this.assetProfileForm.controls.assetClass.value ?? undefined,
assetSubClass:
this.assetProfileForm.controls.assetSubClass.value ?? undefined,
- comment: this.assetProfileForm.controls.comment.value ?? undefined,
+ comment: getStringOrNull(this.assetProfileForm.controls.comment.value),
currency: this.assetProfileForm.controls.currency.value ?? undefined,
dataGatheringFrequency:
this.assetProfileForm.controls.dataGatheringFrequency.value ??
@@ -628,7 +631,7 @@ export class GfAssetProfileDialogComponent implements OnInit {
? this.assetProfileForm.controls.isActive.value
: undefined,
name: this.assetProfileForm.controls.name.value ?? undefined,
- url: this.assetProfileForm.controls.url.value ?? undefined
+ url: getStringOrNull(this.assetProfileForm.controls.url.value)
};
try {
@@ -737,9 +740,10 @@ export class GfAssetProfileDialogComponent implements OnInit {
this.assetProfileForm.controls.scraperConfiguration.controls.headers
.value ?? '{}'
) as Record,
- locale:
+ locale: getStringOrUndefined(
this.assetProfileForm.controls.scraperConfiguration.controls.locale
- ?.value ?? undefined,
+ ?.value
+ ),
mode: this.assetProfileForm.controls.scraperConfiguration.controls
.mode?.value,
selector:
diff --git a/libs/common/src/lib/dtos/update-asset-profile.dto.ts b/libs/common/src/lib/dtos/update-asset-profile.dto.ts
index a6e2230e8e..a8eaad608a 100644
--- a/libs/common/src/lib/dtos/update-asset-profile.dto.ts
+++ b/libs/common/src/lib/dtos/update-asset-profile.dto.ts
@@ -35,7 +35,7 @@ export class UpdateAssetProfileDto {
@IsOptional()
@IsString()
- comment?: string;
+ comment?: string | null;
@IsArray()
@IsOptional()
@@ -96,5 +96,5 @@ export class UpdateAssetProfileDto {
protocols: ['http', 'https'],
require_protocol: true
})
- url?: string;
+ url?: string | null;
}
diff --git a/libs/common/src/lib/helper.spec.ts b/libs/common/src/lib/helper.spec.ts
index d33f104522..7589347240 100644
--- a/libs/common/src/lib/helper.spec.ts
+++ b/libs/common/src/lib/helper.spec.ts
@@ -1,6 +1,8 @@
import {
extractNumberFromString,
getNumberFormatGroup,
+ getStringOrNull,
+ getStringOrUndefined,
isCurrency,
isCurrencySymbol
} from '@ghostfolio/common/helper';
@@ -139,6 +141,62 @@ describe('Helper', () => {
});
});
+ describe('Get string or null', () => {
+ it('String', () => {
+ expect(getStringOrNull('https://ghostfol.io')).toEqual(
+ 'https://ghostfol.io'
+ );
+ });
+
+ it('String (with spaces)', () => {
+ expect(getStringOrNull(' https://ghostfol.io ')).toEqual(
+ 'https://ghostfol.io'
+ );
+ });
+
+ it('Empty string', () => {
+ expect(getStringOrNull('')).toEqual(null);
+ });
+
+ it('Blank string', () => {
+ expect(getStringOrNull(' ')).toEqual(null);
+ });
+
+ it('Null', () => {
+ expect(getStringOrNull(null)).toEqual(null);
+ });
+
+ it('Undefined', () => {
+ expect(getStringOrNull(undefined)).toEqual(null);
+ });
+ });
+
+ describe('Get string or undefined', () => {
+ it('String', () => {
+ expect(getStringOrUndefined('de-DE')).toEqual('de-DE');
+ });
+
+ it('String (with spaces)', () => {
+ expect(getStringOrUndefined(' de-DE ')).toEqual('de-DE');
+ });
+
+ it('Empty string', () => {
+ expect(getStringOrUndefined('')).toEqual(undefined);
+ });
+
+ it('Blank string', () => {
+ expect(getStringOrUndefined(' ')).toEqual(undefined);
+ });
+
+ it('Null', () => {
+ expect(getStringOrUndefined(null)).toEqual(undefined);
+ });
+
+ it('Undefined', () => {
+ expect(getStringOrUndefined(undefined)).toEqual(undefined);
+ });
+ });
+
describe('Is currency', () => {
it('ISO 4217 currency code', () => {
expect(isCurrency('USD')).toEqual(true);
diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts
index db1d3c2a20..7e482838c0 100644
--- a/libs/common/src/lib/helper.ts
+++ b/libs/common/src/lib/helper.ts
@@ -397,6 +397,26 @@ export function getStartOfUtcDate(aDate: Date) {
return date;
}
+export function getStringOrNull(aString: string | null | undefined) {
+ const trimmedString = aString?.trim();
+
+ if (trimmedString) {
+ return trimmedString;
+ }
+
+ return null;
+}
+
+export function getStringOrUndefined(aString: string | null | undefined) {
+ const trimmedString = aString?.trim();
+
+ if (trimmedString) {
+ return trimmedString;
+ }
+
+ return undefined;
+}
+
export function getSum(aArray: Big[]) {
if (aArray?.length > 0) {
return aArray.reduce((a, b) => a.plus(b), new Big(0));
From fa309b57435df39f0b1ad5a25c2b13c3145e2642 Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Sat, 1 Aug 2026 23:16:24 +0200
Subject: [PATCH 3/3] Bugfix/handling of Exclude from Analysis tag in
activities table (#7511)
* Fix handling of Exclude from Analysis tag
* Update changelog
---
CHANGELOG.md | 1 +
libs/common/src/lib/helper.spec.ts | 27 +++++++++++++++++++
libs/common/src/lib/helper.ts | 4 +--
.../activities-table.component.ts | 2 +-
4 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 054a24bdf3..1118f2a692 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+- Fixed the handling of the _Exclude from Analysis_ tag in the activities table
- Resolved a validation error caused by empty strings in the asset profile details dialog of the admin control panel
## 3.39.0 - 2026-08-01
diff --git a/libs/common/src/lib/helper.spec.ts b/libs/common/src/lib/helper.spec.ts
index 7589347240..c4947394f6 100644
--- a/libs/common/src/lib/helper.spec.ts
+++ b/libs/common/src/lib/helper.spec.ts
@@ -1,8 +1,13 @@
+import {
+ TAG_ID_EMERGENCY_FUND,
+ TAG_ID_EXCLUDE_FROM_ANALYSIS
+} from '@ghostfolio/common/config';
import {
extractNumberFromString,
getNumberFormatGroup,
getStringOrNull,
getStringOrUndefined,
+ isAccountExcluded,
isCurrency,
isCurrencySymbol
} from '@ghostfolio/common/helper';
@@ -197,6 +202,28 @@ describe('Helper', () => {
});
});
+ describe('Is account excluded', () => {
+ it('Account with Exclude from Analysis tag', () => {
+ expect(
+ isAccountExcluded({ tags: [{ id: TAG_ID_EXCLUDE_FROM_ANALYSIS }] })
+ ).toEqual(true);
+ });
+
+ it('Account with another tag', () => {
+ expect(
+ isAccountExcluded({ tags: [{ id: TAG_ID_EMERGENCY_FUND }] })
+ ).toEqual(false);
+ });
+
+ it('Account without tags', () => {
+ expect(isAccountExcluded({ tags: [] })).toEqual(false);
+ });
+
+ it('Undefined account', () => {
+ expect(isAccountExcluded(undefined)).toEqual(false);
+ });
+ });
+
describe('Is currency', () => {
it('ISO 4217 currency code', () => {
expect(isCurrency('USD')).toEqual(true);
diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts
index 7e482838c0..58927337ee 100644
--- a/libs/common/src/lib/helper.ts
+++ b/libs/common/src/lib/helper.ts
@@ -476,9 +476,9 @@ export function interpolate(template: string, context: any) {
});
}
-export function isAccountExcluded(account: { tags?: { id: string }[] }) {
+export function isAccountExcluded(account?: { tags?: { id: string }[] }) {
return (
- account.tags?.some(({ id }) => {
+ account?.tags?.some(({ id }) => {
return id === TAG_ID_EXCLUDE_FROM_ANALYSIS;
}) === true
);
diff --git a/libs/ui/src/lib/activities-table/activities-table.component.ts b/libs/ui/src/lib/activities-table/activities-table.component.ts
index 6fac6d1625..7252b00740 100644
--- a/libs/ui/src/lib/activities-table/activities-table.component.ts
+++ b/libs/ui/src/lib/activities-table/activities-table.component.ts
@@ -298,7 +298,7 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit {
public isExcludedFromAnalysis(activity: Activity) {
return (
- (activity.account && isAccountExcluded(activity.account)) ??
+ isAccountExcluded(activity.account) ||
activity.tags?.some(({ id }) => {
return id === TAG_ID_EXCLUDE_FROM_ANALYSIS;
}) === true