3) {
| {{ 'HOME.PLAYLISTS.ADDED' | translate }}:
- {{ item.importDate | date }}
+ {{ item.importDate | date: undefined : undefined : currentLocale() }}
}
@if (item.updateDate) {
| {{ 'HOME.PLAYLISTS.UPDATED' | translate }}:
- {{ item.updateDate | date: 'MMMM d, yyyy, HH:mm' }}
+ {{
+ item.updateDate
+ | date
+ : 'MMMM d, yyyy, HH:mm'
+ : undefined
+ : currentLocale()
+ }}
}
}
diff --git a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts
index 714744e6a..f3a59427b 100644
--- a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts
+++ b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts
@@ -9,12 +9,15 @@ import {
input,
output,
} from '@angular/core';
+import { toSignal } from '@angular/core/rxjs-interop';
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTooltip } from '@angular/material/tooltip';
-import { TranslatePipe } from '@ngx-translate/core';
+import { normalizeDateLocale } from '@iptvnator/pipes';
+import { TranslatePipe, TranslateService } from '@ngx-translate/core';
+import { startWith } from 'rxjs';
import { PortalStatus, PortalStatusService } from 'services';
import { PlaylistMeta } from 'shared-interfaces';
@@ -53,8 +56,19 @@ export class PlaylistItemComponent implements OnInit {
portalStatus: PortalStatus = 'unavailable';
private readonly portalStatusService = inject(PortalStatusService);
+ private readonly translate = inject(TranslateService);
+ private readonly languageTick = toSignal(
+ this.translate.onLangChange.pipe(startWith(null)),
+ { initialValue: null }
+ );
readonly isElectron = !!window.electron;
+ readonly currentLocale = computed(() => {
+ this.languageTick();
+ return normalizeDateLocale(
+ this.translate.currentLang || this.translate.defaultLang
+ );
+ });
async ngOnInit() {
await this.checkPortalStatus();
diff --git a/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.html b/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.html
index b8d3fa2b2..d4d2812f2 100644
--- a/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.html
+++ b/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.html
@@ -41,7 +41,7 @@
{{ title() }}
@if (date()) {
- {{ date() | date: 'd MMM, HH:mm' }}
+ {{ date() | date: 'd MMM, HH:mm' : undefined : currentLocale() }}
}
diff --git a/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.ts b/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.ts
index 85f4f8217..d4466e136 100644
--- a/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.ts
+++ b/libs/portal/shared/ui/src/lib/components/content-card/content-card.component.ts
@@ -2,12 +2,18 @@ import { DatePipe } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
+ computed,
+ inject,
input,
output,
} from '@angular/core';
+import { toSignal } from '@angular/core/rxjs-interop';
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatTooltip } from '@angular/material/tooltip';
+import { normalizeDateLocale } from '@iptvnator/pipes';
+import { TranslateService } from '@ngx-translate/core';
+import { startWith } from 'rxjs';
@Component({
selector: 'app-content-card',
@@ -18,6 +24,12 @@ import { MatTooltip } from '@angular/material/tooltip';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ContentCardComponent {
+ private readonly translate = inject(TranslateService);
+ private readonly languageTick = toSignal(
+ this.translate.onLangChange.pipe(startWith(null)),
+ { initialValue: null }
+ );
+
/** URL of the poster image */
readonly posterUrl = input();
@@ -44,6 +56,12 @@ export class ContentCardComponent {
/** Emitted when the remove button is clicked */
readonly remove = output();
+ readonly currentLocale = computed(() => {
+ this.languageTick();
+ return normalizeDateLocale(
+ this.translate.currentLang || this.translate.defaultLang
+ );
+ });
/** Get the icon for the placeholder based on type */
getPlaceholderIcon(): string {
diff --git a/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.html b/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.html
index 9e28d1b3f..403df1bf0 100644
--- a/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.html
+++ b/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.html
@@ -35,7 +35,10 @@
{{
- formatTime(program.start, program.startTimestamp)
+ (program.startTimestamp
+ ? program.startTimestamp * 1000
+ : program.start
+ ) | date: 'HH:mm'
}}
{{
- formatTime(program.stop, program.stopTimestamp)
+ (program.stopTimestamp
+ ? program.stopTimestamp * 1000
+ : program.stop
+ ) | date: 'HH:mm'
}}
} @else if (!isRadio()) {
diff --git a/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.spec.ts b/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.spec.ts
index 833acec72..32bb99dd8 100644
--- a/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.spec.ts
+++ b/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.spec.ts
@@ -1,3 +1,4 @@
+import { DatePipe } from '@angular/common';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatDialog } from '@angular/material/dialog';
@@ -58,18 +59,11 @@ describe('ChannelListItemComponent', () => {
fixture.nativeElement.querySelectorAll('.epg-time'),
(element: Element) => element.textContent?.trim() ?? ''
);
+ const datePipe = new DatePipe('en-US');
expect(times).toEqual([
- new Date(startTimestamp * 1000).toLocaleTimeString('en-US', {
- hour: '2-digit',
- minute: '2-digit',
- hour12: false,
- }),
- new Date(stopTimestamp * 1000).toLocaleTimeString('en-US', {
- hour: '2-digit',
- minute: '2-digit',
- hour12: false,
- }),
+ datePipe.transform(startTimestamp * 1000, 'HH:mm') ?? '',
+ datePipe.transform(stopTimestamp * 1000, 'HH:mm') ?? '',
]);
});
diff --git a/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.ts b/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.ts
index b30733ce3..1c7b65f5d 100644
--- a/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.ts
+++ b/libs/ui/components/src/lib/channel-list-container/channel-list-item/channel-list-item.component.ts
@@ -1,5 +1,5 @@
import { DragDropModule } from '@angular/cdk/drag-drop';
-import { NgStyle } from '@angular/common';
+import { DatePipe, NgStyle } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
@@ -23,6 +23,7 @@ import { EpgProgram } from 'shared-interfaces';
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './channel-list-item.component.html',
imports: [
+ DatePipe,
DragDropModule,
MatIcon,
MatIconButton,
@@ -64,30 +65,6 @@ export class ChannelListItemComponent {
});
}
- /**
- * Formats time for display (HH:mm)
- */
- formatTime(
- dateString: string | number,
- timestampSeconds?: number | null
- ): string {
- const unixTimestamp = Number(timestampSeconds);
- const date =
- Number.isFinite(unixTimestamp) && unixTimestamp > 0
- ? new Date(unixTimestamp * 1000)
- : new Date(dateString);
-
- if (Number.isNaN(date.getTime())) {
- return '';
- }
-
- return date.toLocaleTimeString('en-US', {
- hour: '2-digit',
- minute: '2-digit',
- hour12: false,
- });
- }
-
/**
* Opens the dialog with details about the current EPG program
* @param program EPG program to show details for
diff --git a/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.html b/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.html
index d60cfc0f7..f0f924001 100644
--- a/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.html
+++ b/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.html
@@ -3,11 +3,26 @@