From 853914ca140f61ff0c19f64db50d14cbb2ab001b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 20 Oct 2026 07:40:18 +0200 Subject: [PATCH] Bugfix/localization of date pickers (#8232) * Fix localization of date pickers * Update changelog --- CHANGELOG.md | 5 +++++ apps/client/src/app/app.component.ts | 18 +++++++++++++++++- ...create-or-update-access-dialog.component.ts | 6 +----- ...eate-or-update-activity-dialog.component.ts | 13 +------------ .../account-balances.component.ts | 9 +-------- ...ical-market-data-editor-dialog.component.ts | 11 +---------- 6 files changed, 26 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e34aa4caa..c31fecf7b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the performance of the historical market data table of the admin control panel by loading only the latest market price per asset profile - Introduced a cooldown of 12 hours for the asset profile and exchange rate gathering on activity creation by retaining the completed jobs +### Fixed + +- Fixed the missing localization of the date picker in the _FIRE_ calculator +- Fixed the missing localization of the date picker in the asset profile details dialog of the admin control panel + ## 3.88.0 - 2026-10-17 ### Added diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts index c9e124723d..53d3505a1c 100644 --- a/apps/client/src/app/app.component.ts +++ b/apps/client/src/app/app.component.ts @@ -25,6 +25,7 @@ import { OnInit } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { DateAdapter } from '@angular/material/core'; import { MatDialog } from '@angular/material/dialog'; import { Title } from '@angular/platform-browser'; import { @@ -39,7 +40,7 @@ import { Chart } from 'chart.js'; import { addIcons } from 'ionicons'; import { openOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { filter } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map } from 'rxjs/operators'; import { GfFooterComponent } from './components/footer/footer.component'; import { GfHeaderComponent } from './components/header/header.component'; @@ -75,6 +76,7 @@ export class GfAppComponent implements OnInit { private readonly changeDetectorRef = inject(ChangeDetectorRef); private readonly dataService = inject(DataService); + private readonly dateAdapter = inject>(DateAdapter); private readonly destroyRef = inject(DestroyRef); private readonly deviceDetectorService = inject(DeviceDetectorService); private readonly dialog = inject(MatDialog); @@ -212,6 +214,20 @@ export class GfAppComponent implements OnInit { this.changeDetectorRef.markForCheck(); }); + this.userService.stateChanged + .pipe( + map(({ user }) => { + return user?.settings.locale; + }), + distinctUntilChanged(), + takeUntilDestroyed(this.destroyRef) + ) + .subscribe((locale) => { + if (locale) { + this.dateAdapter.setLocale(locale); + } + }); + this.userService.stateChanged .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { diff --git a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts index afb0e2cea3..17d671c9b2 100644 --- a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts +++ b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts @@ -1,5 +1,5 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { DEFAULT_LOCALE, MCP_ENDPOINT } from '@ghostfolio/common/config'; +import { MCP_ENDPOINT } from '@ghostfolio/common/config'; import { CreateAccessDto, UpdateAccessDto } from '@ghostfolio/common/dtos'; import { canApplyFiltersToAccess } from '@ghostfolio/common/helper'; import { Filter, PortfolioPosition } from '@ghostfolio/common/interfaces'; @@ -48,7 +48,6 @@ import { Validators } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; -import { DateAdapter } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MAT_DIALOG_DATA, @@ -108,7 +107,6 @@ export class GfCreateOrUpdateAccessDialogComponent implements OnInit { private readonly data = inject(MAT_DIALOG_DATA); - private readonly dateAdapter = inject>(DateAdapter); private readonly dataService = inject(DataService); private readonly destroyRef = inject(DestroyRef); @@ -189,8 +187,6 @@ export class GfCreateOrUpdateAccessDialogComponent implements OnInit { this.hasExperimentalFeatures = settings.isExperimentalFeatures ?? false; this.tags = getTagFilters(tags); - this.dateAdapter.setLocale(settings.locale ?? DEFAULT_LOCALE); - this.changeDetectorRef.markForCheck(); }); diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts index c041b565aa..d3bc34acee 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts @@ -6,10 +6,7 @@ import { DEFAULT_LOCALE } from '@ghostfolio/common/config'; import { CreateOrderDto, UpdateOrderDto } from '@ghostfolio/common/dtos'; -import { - getDateFormatString, - getStringOrNull -} from '@ghostfolio/common/helper'; +import { getStringOrNull } from '@ghostfolio/common/helper'; import { AssetClassSelectorOption, LookupItem @@ -41,7 +38,6 @@ import { } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; -import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MAT_DIALOG_DATA, @@ -102,7 +98,6 @@ export class GfCreateOrUpdateActivityDialogComponent { protected currencies: string[] = []; protected currencyOfAssetProfile: string | undefined; protected currentMarketPrice: number | null = null; - protected defaultDateFormat: string; protected defaultLookupItems: LookupItem[] = []; protected hasPermissionToCreateOwnTag: boolean; protected isLoading = false; @@ -119,7 +114,6 @@ export class GfCreateOrUpdateActivityDialogComponent { private readonly changeDetectorRef = inject(ChangeDetectorRef); private readonly dataService = inject(DataService); - private readonly dateAdapter = inject>(DateAdapter); private readonly destroyRef = inject(DestroyRef); private readonly dialogRef = inject>(MatDialogRef); @@ -127,7 +121,6 @@ export class GfCreateOrUpdateActivityDialogComponent { private readonly impersonationStorageService = inject( ImpersonationStorageService ); - private locale = inject(MAT_DATE_LOCALE); private readonly userService = inject(UserService); public constructor() { @@ -143,15 +136,11 @@ export class GfCreateOrUpdateActivityDialogComponent { !this.impersonationStorageService.getId() && hasPermission(this.data.user?.permissions, permissions.createOwnTag); - this.locale = this.data.user.settings.locale ?? DEFAULT_LOCALE; this.mode = this.data.activity?.id ? 'update' : 'create'; - this.dateAdapter.setLocale(this.locale); - const { currencies } = this.dataService.fetchInfo(); this.currencies = currencies; - this.defaultDateFormat = getDateFormatString(this.locale); this.dataService .fetchPortfolioHoldings({ diff --git a/libs/ui/src/lib/account-balances/account-balances.component.ts b/libs/ui/src/lib/account-balances/account-balances.component.ts index 678650b2cb..715b4af0ec 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.ts +++ b/libs/ui/src/lib/account-balances/account-balances.component.ts @@ -11,7 +11,6 @@ import { Component, EventEmitter, OnChanges, - OnInit, Output, effect, inject, @@ -25,7 +24,6 @@ import { ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; -import { DateAdapter } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; @@ -63,7 +61,7 @@ import { GfValueComponent } from '../value'; styleUrls: ['./account-balances.component.scss'], templateUrl: './account-balances.component.html' }) -export class GfAccountBalancesComponent implements OnChanges, OnInit { +export class GfAccountBalancesComponent implements OnChanges { @Output() accountBalanceCreated = new EventEmitter(); @Output() accountBalanceDeleted = new EventEmitter(); @@ -94,7 +92,6 @@ export class GfAccountBalancesComponent implements OnChanges, OnInit { >(); public maxDate = new Date(); - private dateAdapter = inject>(DateAdapter); private notificationService = inject(NotificationService); public constructor() { @@ -112,10 +109,6 @@ export class GfAccountBalancesComponent implements OnChanges, OnInit { }); } - public ngOnInit() { - this.dateAdapter.setLocale(this.locale()); - } - public ngOnChanges() { if (this.accountBalances()) { this.dataSource = new MatTableDataSource(this.accountBalances()); diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts index 4f8540974f..358dbbbcd4 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts @@ -6,7 +6,6 @@ import { Component, CUSTOM_ELEMENTS_SCHEMA, DestroyRef, - OnInit, inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @@ -17,7 +16,6 @@ import { Validators } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; -import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MAT_DIALOG_DATA, @@ -50,7 +48,7 @@ import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces' styleUrls: ['./historical-market-data-editor-dialog.scss'], templateUrl: 'historical-market-data-editor-dialog.html' }) -export class GfHistoricalMarketDataEditorDialogComponent implements OnInit { +export class GfHistoricalMarketDataEditorDialogComponent { public readonly data = inject(MAT_DIALOG_DATA); @@ -60,23 +58,16 @@ export class GfHistoricalMarketDataEditorDialogComponent implements OnInit { }); private readonly destroyRef = inject(DestroyRef); - private readonly locale = - this.data.user.settings.locale ?? inject(MAT_DATE_LOCALE); public constructor( private adminService: AdminService, private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, - private dateAdapter: DateAdapter, public dialogRef: MatDialogRef ) { addIcons({ calendarClearOutline, refreshOutline }); } - public ngOnInit() { - this.dateAdapter.setLocale(this.locale); - } - public onCancel() { this.dialogRef.close({ withRefresh: false }); }