+
+
+
+ {{ 'SETTINGS.BACKUP_INCLUDE_SECRETS' | translate }}
+
+
+
+
@if (isPwa()) {
{{ 'SETTINGS.EPG_NOTE' | translate }}
diff --git a/apps/web/src/app/settings/settings-backup-section.component.ts b/apps/web/src/app/settings/settings-backup-section.component.ts
index 9cfb5af6c..4db2d5c54 100644
--- a/apps/web/src/app/settings/settings-backup-section.component.ts
+++ b/apps/web/src/app/settings/settings-backup-section.component.ts
@@ -1,26 +1,49 @@
-import { Component, input, output, ViewEncapsulation } from '@angular/core';
+import {
+ Component,
+ inject,
+ input,
+ output,
+ ViewEncapsulation,
+} from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
+import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { TranslateModule } from '@ngx-translate/core';
+import { SettingsBackupFacade } from './settings-backup.facade';
@Component({
selector: 'app-settings-backup-section',
imports: [
MatButtonModule,
+ MatCheckboxModule,
MatIconModule,
MatProgressSpinnerModule,
TranslateModule,
],
templateUrl: './settings-backup-section.component.html',
encapsulation: ViewEncapsulation.None,
- styles: [':host { display: contents; }'],
+ styles: [
+ `
+ :host {
+ display: contents;
+ }
+
+ .settings-backup-warning--secrets {
+ color: var(--mat-sys-error);
+ font-weight: 600;
+ }
+ `,
+ ],
})
export class SettingsBackupSectionComponent {
+ private readonly backupFacade = inject(SettingsBackupFacade);
+
readonly activeSection = input.required
();
readonly isPwa = input(false);
readonly isRemovingAllPlaylists = input(false);
readonly isExportingData = input(false);
+ readonly includeSecrets = this.backupFacade.includeSecrets;
readonly importData = output();
readonly exportData = output();
diff --git a/apps/web/src/app/settings/settings-backup.facade.ts b/apps/web/src/app/settings/settings-backup.facade.ts
index 6aa377b4c..4c83e7c1a 100644
--- a/apps/web/src/app/settings/settings-backup.facade.ts
+++ b/apps/web/src/app/settings/settings-backup.facade.ts
@@ -1,12 +1,20 @@
import { inject, Injectable, signal } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import { PlaylistActions } from '@iptvnator/m3u-state';
import {
PlaylistBackupImportSummary,
PlaylistBackupService,
+ PlaylistBackupXtreamCredentials,
+ PlaylistBackupXtreamCredentialsRequest,
RuntimeCapabilitiesService,
} from '@iptvnator/services';
+import { firstValueFrom } from 'rxjs';
+import {
+ SettingsBackupCredentialsDialogComponent,
+ SettingsBackupCredentialsDialogData,
+} from './settings-backup-credentials-dialog.component';
import { SettingsSnackbarService } from './settings-snackbar.service';
@Injectable()
@@ -16,7 +24,9 @@ export class SettingsBackupFacade {
private readonly settingsSnackbar = inject(SettingsSnackbarService);
private readonly store = inject(Store);
private readonly translate = inject(TranslateService);
+ private readonly matDialog = inject(MatDialog);
+ readonly includeSecrets = signal(false);
readonly isExportingData = signal(false);
async exportData(waitForUiFeedbackFrame: () => Promise) {
@@ -28,7 +38,9 @@ export class SettingsBackupFacade {
await waitForUiFeedbackFrame();
try {
- const backup = await this.playlistBackupService.exportBackup();
+ const backup = await this.playlistBackupService.exportBackup({
+ includeSecrets: this.includeSecrets(),
+ });
if (this.runtime.supportsDesktopFileSave && window.electron) {
const savePath = await window.electron.saveFileDialog(
@@ -77,7 +89,11 @@ export class SettingsBackupFacade {
try {
const summary = await this.playlistBackupService.importBackup(
- await file.text()
+ await file.text(),
+ {
+ resolveXtreamCredentials: (request) =>
+ this.resolveXtreamCredentials(request),
+ }
);
if (summary.imported > 0 || summary.merged > 0) {
@@ -124,6 +140,36 @@ export class SettingsBackupFacade {
window.URL.revokeObjectURL(url);
}
+ private async resolveXtreamCredentials(
+ request: PlaylistBackupXtreamCredentialsRequest
+ ): Promise {
+ const dialogRef = this.matDialog.open<
+ SettingsBackupCredentialsDialogComponent,
+ SettingsBackupCredentialsDialogData,
+ PlaylistBackupXtreamCredentials | null
+ >(SettingsBackupCredentialsDialogComponent, {
+ data: {
+ playlistTitle: request.title,
+ serverHost: this.getServerHost(request.serverUrl),
+ },
+ maxWidth: 'calc(100vw - 32px)',
+ width: '440px',
+ });
+
+ return (await firstValueFrom(dialogRef.afterClosed())) ?? null;
+ }
+
+ private getServerHost(serverUrl: string): string {
+ try {
+ const normalizedUrl = serverUrl.includes('://')
+ ? serverUrl
+ : `https://${serverUrl}`;
+ return new URL(normalizedUrl).host;
+ } catch {
+ return '';
+ }
+ }
+
private buildBackupImportSummary(
summary: PlaylistBackupImportSummary
): string {
diff --git a/apps/web/src/app/settings/settings.component.spec.ts b/apps/web/src/app/settings/settings.component.spec.ts
index 473326b72..3eb7b8fbd 100644
--- a/apps/web/src/app/settings/settings.component.spec.ts
+++ b/apps/web/src/app/settings/settings.component.spec.ts
@@ -46,6 +46,8 @@ import {
} from '@iptvnator/shared/interfaces';
import { SettingsComponent } from './settings.component';
import { AppUpdateReleaseNotesDialogComponent } from './app-update-release-notes-dialog.component';
+import { SettingsBackupCredentialsDialogComponent } from './settings-backup-credentials-dialog.component';
+import { SettingsBackupSectionComponent } from './settings-backup-section.component';
import { signal } from '@angular/core';
import { SettingsContextService } from '@iptvnator/workspace/shell/util';
@@ -1192,9 +1194,125 @@ describe('SettingsComponent', () => {
'/tmp/backup.json',
'{}'
);
+ expect(playlistBackupService.exportBackup).toHaveBeenCalledWith({
+ includeSecrets: false,
+ });
expect(component.isExportingData()).toBe(false);
});
+ it('includes credentials only after the backup checkbox is enabled', async () => {
+ const backupSection = fixture.debugElement.query(
+ By.directive(SettingsBackupSectionComponent)
+ ).componentInstance as SettingsBackupSectionComponent;
+
+ expect(backupSection.includeSecrets()).toBe(false);
+
+ backupSection.includeSecrets.set(true);
+ await component.exportData();
+
+ expect(playlistBackupService.exportBackup).toHaveBeenCalledWith({
+ includeSecrets: true,
+ });
+ });
+
+ it('shows both redacted-backup and secret-export guidance', () => {
+ const backupSection = fixture.debugElement.query(
+ By.directive(SettingsBackupSectionComponent)
+ );
+
+ expect(backupSection.nativeElement.textContent).toContain(
+ 'SETTINGS.BACKUP_REDACTED_WARNING'
+ );
+ expect(backupSection.nativeElement.textContent).not.toContain(
+ 'SETTINGS.BACKUP_SECRETS_WARNING'
+ );
+
+ (
+ backupSection.componentInstance as SettingsBackupSectionComponent
+ ).includeSecrets.set(true);
+ fixture.detectChanges();
+
+ expect(backupSection.nativeElement.textContent).toContain(
+ 'SETTINGS.BACKUP_SECRETS_WARNING'
+ );
+ });
+
+ it('resolves redacted Xtream credentials through the dialog and reports skipped entries', async () => {
+ const backupJson = JSON.stringify({
+ kind: 'iptvnator-playlist-backup',
+ version: 1,
+ exportedAt: '2026-04-21T00:00:00.000Z',
+ includeSecrets: false,
+ playlists: [],
+ });
+ const file = {
+ text: jest.fn().mockResolvedValue(backupJson),
+ } as unknown as File;
+ const inputClickSpy = jest
+ .spyOn(HTMLInputElement.prototype, 'click')
+ .mockImplementation(function (this: HTMLInputElement) {
+ Object.defineProperty(this, 'files', {
+ configurable: true,
+ value: [file],
+ });
+ this.dispatchEvent(new Event('change'));
+ });
+ const dialogOpenSpy = jest
+ .spyOn(privateApi(component).matDialog, 'open')
+ .mockReturnValue({
+ afterClosed: () => of(undefined),
+ } as unknown as ReturnType);
+ (
+ playlistBackupService.importBackup as jest.Mock
+ ).mockImplementationOnce(async (_json, options) => {
+ const credentials = await options.resolveXtreamCredentials({
+ exportedId: 'xtream-redacted',
+ title: 'Living room',
+ serverUrl:
+ 'https://viewer:secret@provider.example:8443/player_api.php?token=private',
+ });
+
+ expect(credentials).toBeNull();
+
+ return {
+ imported: 0,
+ merged: 0,
+ skipped: 1,
+ failed: 0,
+ errors: [],
+ };
+ });
+
+ try {
+ component.importData();
+ await fixture.whenStable();
+
+ expect(playlistBackupService.importBackup).toHaveBeenCalledWith(
+ backupJson,
+ {
+ resolveXtreamCredentials: expect.any(Function),
+ }
+ );
+ expect(dialogOpenSpy).toHaveBeenCalledWith(
+ SettingsBackupCredentialsDialogComponent,
+ expect.objectContaining({
+ data: {
+ playlistTitle: 'Living room',
+ serverHost: 'provider.example:8443',
+ },
+ })
+ );
+ expect(snackBar.open).toHaveBeenCalledWith(
+ expect.stringContaining('1 skipped'),
+ undefined,
+ expect.any(Object)
+ );
+ } finally {
+ dialogOpenSpy.mockRestore();
+ inputClickSpy.mockRestore();
+ }
+ });
+
it('falls back to browser backup download when desktop file-save preload is incomplete', async () => {
fixture.destroy();
const saveFileDialog = jest.fn().mockResolvedValue('/tmp/backup.json');
diff --git a/apps/web/src/assets/i18n/ar.json b/apps/web/src/assets/i18n/ar.json
index 9c2ef982f..c4678116d 100644
--- a/apps/web/src/assets/i18n/ar.json
+++ b/apps/web/src/assets/i18n/ar.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "تصدير",
"EXPORTING_DATA": "جارٍ التصدير…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/ary.json b/apps/web/src/assets/i18n/ary.json
index 6f8a3ca06..f39bb7ce1 100644
--- a/apps/web/src/assets/i18n/ary.json
+++ b/apps/web/src/assets/i18n/ary.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "صدّر",
"EXPORTING_DATA": "جاري التصدير…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/by.json b/apps/web/src/assets/i18n/by.json
index 12ef0bfb5..d8d0a5993 100644
--- a/apps/web/src/assets/i18n/by.json
+++ b/apps/web/src/assets/i18n/by.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Экспарт",
"EXPORTING_DATA": "Экспартаванне...",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/de.json b/apps/web/src/assets/i18n/de.json
index 8786a0736..1e879abba 100644
--- a/apps/web/src/assets/i18n/de.json
+++ b/apps/web/src/assets/i18n/de.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Export",
"EXPORTING_DATA": "Wird exportiert …",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/el.json b/apps/web/src/assets/i18n/el.json
index 8ca4913ce..2cf4aaaed 100644
--- a/apps/web/src/assets/i18n/el.json
+++ b/apps/web/src/assets/i18n/el.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Εξαγωγή",
"EXPORTING_DATA": "Εξαγωγή…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/en.json b/apps/web/src/assets/i18n/en.json
index 130b118e9..b938cb374 100644
--- a/apps/web/src/assets/i18n/en.json
+++ b/apps/web/src/assets/i18n/en.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Export",
"EXPORTING_DATA": "Exporting…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/es.json b/apps/web/src/assets/i18n/es.json
index 256f10042..16ca28003 100644
--- a/apps/web/src/assets/i18n/es.json
+++ b/apps/web/src/assets/i18n/es.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Exportar",
"EXPORTING_DATA": "Exportando…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/fr.json b/apps/web/src/assets/i18n/fr.json
index cb86e2daa..569c269f6 100644
--- a/apps/web/src/assets/i18n/fr.json
+++ b/apps/web/src/assets/i18n/fr.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Exporter",
"EXPORTING_DATA": "Exportation…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/hu.json b/apps/web/src/assets/i18n/hu.json
index 83183c4a4..5c7991b3a 100644
--- a/apps/web/src/assets/i18n/hu.json
+++ b/apps/web/src/assets/i18n/hu.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Exportálás",
"EXPORTING_DATA": "Exportálás…",
"REMOVE_ALL": "Az összes lejátszási lista és kapcsolódó adat törlése",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Összes törlése",
"REMOVE_ALL_DESCRIPTION": "Az alkalmazásban tárolt összes M3U-, Xtream- és Stalker-lejátszási lista törlése.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/it.json b/apps/web/src/assets/i18n/it.json
index a57ea5146..e46ef744c 100644
--- a/apps/web/src/assets/i18n/it.json
+++ b/apps/web/src/assets/i18n/it.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Esporta",
"EXPORTING_DATA": "Esportazione...",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/ja.json b/apps/web/src/assets/i18n/ja.json
index ccbdfeddb..4a04a6c1f 100644
--- a/apps/web/src/assets/i18n/ja.json
+++ b/apps/web/src/assets/i18n/ja.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "エクスポート",
"EXPORTING_DATA": "エクスポート中…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/ko.json b/apps/web/src/assets/i18n/ko.json
index 1c7351c29..e9d81cf31 100644
--- a/apps/web/src/assets/i18n/ko.json
+++ b/apps/web/src/assets/i18n/ko.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "내보내다",
"EXPORTING_DATA": "내보내는 중…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/nl.json b/apps/web/src/assets/i18n/nl.json
index c28d9c7e3..c2389039e 100644
--- a/apps/web/src/assets/i18n/nl.json
+++ b/apps/web/src/assets/i18n/nl.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Exporteren",
"EXPORTING_DATA": "Exporteren…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/pl.json b/apps/web/src/assets/i18n/pl.json
index 46f5db3c9..174c8e85f 100644
--- a/apps/web/src/assets/i18n/pl.json
+++ b/apps/web/src/assets/i18n/pl.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Eksportuj",
"EXPORTING_DATA": "Eksportowanie…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/pt.json b/apps/web/src/assets/i18n/pt.json
index da02cce09..22e760367 100644
--- a/apps/web/src/assets/i18n/pt.json
+++ b/apps/web/src/assets/i18n/pt.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Exportar",
"EXPORTING_DATA": "Exportando…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/ru.json b/apps/web/src/assets/i18n/ru.json
index c2eb29748..65dba30f2 100644
--- a/apps/web/src/assets/i18n/ru.json
+++ b/apps/web/src/assets/i18n/ru.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Экспорт",
"EXPORTING_DATA": "Экспорт…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/tr.json b/apps/web/src/assets/i18n/tr.json
index 5df212dc2..e25b487e0 100644
--- a/apps/web/src/assets/i18n/tr.json
+++ b/apps/web/src/assets/i18n/tr.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "Dışa Aktar",
"EXPORTING_DATA": "Dışa aktarılıyor…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/zh.json b/apps/web/src/assets/i18n/zh.json
index 3f0dc3ac2..d5ed0ca5c 100644
--- a/apps/web/src/assets/i18n/zh.json
+++ b/apps/web/src/assets/i18n/zh.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "出口",
"EXPORTING_DATA": "导出中…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
diff --git a/apps/web/src/assets/i18n/zhtw.json b/apps/web/src/assets/i18n/zhtw.json
index 042b7c831..bef80d0c6 100644
--- a/apps/web/src/assets/i18n/zhtw.json
+++ b/apps/web/src/assets/i18n/zhtw.json
@@ -354,6 +354,22 @@
"EXPORT_DATA": "匯出",
"EXPORTING_DATA": "正在匯出…",
"REMOVE_ALL": "Delete all playlists and playlist data",
+ "BACKUP_CONTENTS": "Backup contents",
+ "BACKUP_INCLUDE_SECRETS": "Include portal credentials and Stalker device identity",
+ "BACKUP_REDACTED_WARNING": "Portal passwords and Stalker device identity are excluded by default. Even a redacted backup can still contain MAC addresses, portal hosts/source URLs, and private URLs embedded in raw M3U playlist data.",
+ "BACKUP_SECRETS_WARNING": "Warning: this export will include portal usernames and passwords plus Stalker device identity fields. Store the backup securely.",
+ "BACKUP_CREDENTIALS_DIALOG": {
+ "TITLE": "Xtream credentials required",
+ "MESSAGE": "This redacted backup does not contain the credentials for this playlist.",
+ "PLAYLIST": "Playlist",
+ "SERVER": "Server",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "USERNAME_REQUIRED": "Enter a username.",
+ "PASSWORD_REQUIRED": "Enter a password.",
+ "SKIP": "Skip playlist",
+ "IMPORT": "Import playlist"
+ },
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {