mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-15 21:56:18 -08:00
feat(epg): accept local XMLTV files as EPG sources (#1600)
* feat(epg): accept local XMLTV files as EPG sources Settings → EPG and the playlist dialog accepted `file://` in their form pattern, but the main process rejected everything except http(s), so a local XMLTV entry saved fine and then failed on import. Both surfaces now take a remote link, a `file:` URL, an absolute POSIX path or a Windows drive/UNC path (`classifyEpgSourceReference` in shared/interfaces), and the settings section spells out the accepted formats with examples. The EPG worker opens every source through `openEpgSourceStream`: remote links keep the validated-redirect client and trust policy, local files are read from disk behind the signature-sniffing optional gunzip stage, so .xml, .xml.gz and extension-less gzip all parse. Only hand-typed sources may be local: `extractM3uEpgUrls` harvests http(s) links only from M3U headers, since the local branch bypasses `validateRemoteUrl`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * feat(epg): pick local XMLTV files with a native file dialog A folder button beside each EPG source row (Settings → EPG and the playlist dialog) opens the native open-file dialog and writes the chosen absolute path into the row. New `EPG_OPEN_FILE_DIALOG` IPC behind `ElectronBridgeApi.openEpgFileDialog`, gated in the renderer by `RuntimeCapabilitiesService.supportsEpgFilePicker`. The row's refresh/remove buttons carry `data-test-id`s now, and the EPG e2e suites address them by id instead of index, since the folder button became the first button in a row. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(epg): authorize local XMLTV files in the main process Review follow-up (Greptile P1, Codex P1). The renderer hands source strings to FETCH_EPG/EPG_FORCE_FETCH unchanged, so the form validator alone could not enforce the provenance rule: a compromised renderer, or a legacy `file://` entry an older version stored from an M3U header, could name any file on disk. `EpgWorkerService.startFetch` now asks a main-process `EpgLocalSourceAuthorizer` before a local path reaches the worker: a path the native picker returned is trusted at once, a hand-typed path is confirmed once in a native message box the renderer cannot fake, and a refusal is reported in the progress panel. Allowed paths persist under TRUSTED_LOCAL_EPG_SOURCES in the main-process config. The worker opens its local branch only when main set `allowLocalFile`; the service defaults to deny-all until epg.events installs the persisted authorizer. `resolvePlaylistEpgSourceState` and `filterPlaylistEpgUrlsForFetch` drop a stored non-remote entry unless it is also in `manualEpgUrls`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(epg): fail a refused local EPG fetch instead of resolving it Review follow-up (Codex P2). A denied native confirmation now rejects the fetch after reporting the error row, so handleFetchEpg and the renderer's fetch result cannot claim the file was read. Also restores the unrelated CLAUDE.md paragraph an earlier formatter pass had reflowed into a list. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(epg): cancel a local source retired during its authorization prompt Review follow-up (Codex P2). startFetch keeps the request generation captured before awaiting the native confirmation and rechecks it afterwards: a source retired meanwhile ends as cancelled instead of starting an import that a pending clear would then have to await. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test(epg): leave the local XMLTV e2e with a pristine settings form The local-file test ended with the EPG source field still dirty, which arms the main-process close guard: the app then waited for the unsaved changes dialog instead of closing, the close timeout killed it, and on Windows the killed process kept iptvnator.db busy (EBUSY on the data-dir cleanup) and hung the Playwright worker teardown. Discarding the form before the app closes takes the test from 15 s to 4 s locally. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: 4gray <fourgray@proton.me> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
65 files changed
+1621
-149
No files matched your search
@@ -70,6 +70,19 @@
|
||||
</div>
|
||||
|
||||
<div class="setting-item setting-item--full-control">
|
||||
<div class="setting-item__meta" data-test-id="epg-source-formats">
|
||||
<h4>{{ 'SETTINGS.EPG_SOURCE_LIST_TITLE' | translate }}</h4>
|
||||
<p>{{ 'SETTINGS.EPG_SOURCE_FORMATS_HINT' | translate }}</p>
|
||||
<p class="epg-sources__formats-examples">
|
||||
<span>{{
|
||||
'SETTINGS.EPG_SOURCE_FORMATS_EXAMPLES' | translate
|
||||
}}</span>
|
||||
<code>https://example.org/guide.xml.gz</code>
|
||||
<code>/home/you/epg/guide.xml</code>
|
||||
<code>C:\epg\guide.xml.gz</code>
|
||||
<code>file:///…/guide.xml</code>
|
||||
</p>
|
||||
</div>
|
||||
<div class="setting-item__control">
|
||||
<ng-container formArrayName="epgUrl">
|
||||
@if (epgUrl().length === 0) {
|
||||
@@ -102,7 +115,8 @@
|
||||
}}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="url"
|
||||
type="text"
|
||||
spellcheck="false"
|
||||
[formControlName]="i"
|
||||
#epgField
|
||||
/>
|
||||
@@ -115,12 +129,31 @@
|
||||
[url]="epgField.value"
|
||||
/>
|
||||
}
|
||||
@if (canBrowseFiles()) {
|
||||
<button
|
||||
mat-icon-button
|
||||
[matTooltip]="
|
||||
'SETTINGS.BROWSE_EPG_FILE'
|
||||
| translate
|
||||
"
|
||||
[attr.aria-label]="
|
||||
'SETTINGS.BROWSE_EPG_FILE'
|
||||
| translate
|
||||
"
|
||||
type="button"
|
||||
data-test-id="epg-source-browse"
|
||||
(click)="browseEpgSource.emit(i)"
|
||||
>
|
||||
<mat-icon>folder_open</mat-icon>
|
||||
</button>
|
||||
}
|
||||
<button
|
||||
mat-icon-button
|
||||
[matTooltip]="
|
||||
'SETTINGS.REFRESH_EPG' | translate
|
||||
"
|
||||
type="button"
|
||||
data-test-id="epg-source-refresh"
|
||||
[disabled]="epgField.value === ''"
|
||||
(click)="refreshEpg.emit(epgUrl().value[i])"
|
||||
>
|
||||
@@ -132,6 +165,7 @@
|
||||
'SETTINGS.REMOVE_EPG_SOURCE' | translate
|
||||
"
|
||||
type="button"
|
||||
data-test-id="epg-source-remove"
|
||||
(click)="removeEpgSource.emit(i)"
|
||||
>
|
||||
<mat-icon>remove</mat-icon>
|
||||
|
||||
@@ -34,9 +34,11 @@ export class SettingsEpgSectionComponent {
|
||||
readonly form = input.required<FormGroup>();
|
||||
readonly epgUrl = input.required<FormArray>();
|
||||
readonly isClearingEpgData = input(false);
|
||||
readonly canBrowseFiles = input(false);
|
||||
readonly epgViewModeOptions = input.required<EpgViewModeOption[]>();
|
||||
|
||||
readonly refreshEpg = output<string>();
|
||||
readonly browseEpgSource = output<number>();
|
||||
readonly removeEpgSource = output<number>();
|
||||
readonly addEpgSource = output<void>();
|
||||
readonly refreshAllEpg = output<void>();
|
||||
|
||||
@@ -174,4 +174,50 @@ describe('SettingsEpgFacade', () => {
|
||||
|
||||
expect(epgService.fetchEpg).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('browse', () => {
|
||||
it('writes the picked file into the row and dirties the form', async () => {
|
||||
formFacade.setEpgUrls([
|
||||
'https://epg.example.org/guide.xml',
|
||||
'https://epg.example.org/old.xml',
|
||||
]);
|
||||
(epgBridge.pickEpgFile as jest.Mock).mockResolvedValue(
|
||||
'/home/user/epg/guide.xml.gz'
|
||||
);
|
||||
|
||||
await facade.browse(1);
|
||||
|
||||
expect(formFacade.epgUrl.at(1).value).toBe(
|
||||
'/home/user/epg/guide.xml.gz'
|
||||
);
|
||||
expect(formFacade.epgUrl.at(0).value).toBe(
|
||||
'https://epg.example.org/guide.xml'
|
||||
);
|
||||
expect(formFacade.epgUrl.at(1).dirty).toBe(true);
|
||||
expect(formFacade.form.dirty).toBe(true);
|
||||
});
|
||||
|
||||
it('leaves the row untouched when the picker is cancelled', async () => {
|
||||
formFacade.setEpgUrls(['https://epg.example.org/guide.xml']);
|
||||
(epgBridge.pickEpgFile as jest.Mock).mockResolvedValue(null);
|
||||
|
||||
await facade.browse(0);
|
||||
|
||||
expect(formFacade.epgUrl.at(0).value).toBe(
|
||||
'https://epg.example.org/guide.xml'
|
||||
);
|
||||
expect(formFacade.form.dirty).toBe(false);
|
||||
});
|
||||
|
||||
it('never opens the picker without the capability or for a missing row', async () => {
|
||||
formFacade.setEpgUrls(['https://epg.example.org/guide.xml']);
|
||||
await facade.browse(5);
|
||||
expect(epgBridge.pickEpgFile).not.toHaveBeenCalled();
|
||||
|
||||
(epgBridge as { supportsFilePicker: boolean }).supportsFilePicker =
|
||||
false;
|
||||
await facade.browse(0);
|
||||
expect(epgBridge.pickEpgFile).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -25,6 +25,29 @@ export class SettingsEpgFacade {
|
||||
|
||||
readonly isClearing = signal(false);
|
||||
|
||||
get supportsFilePicker(): boolean {
|
||||
return this.epgBridge.supportsFilePicker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Native picker for a local XMLTV file. The chosen absolute path becomes
|
||||
* the value of row `index`; a cancelled dialog leaves the row untouched.
|
||||
*/
|
||||
async browse(index: number): Promise<void> {
|
||||
const control = this.formFacade.epgUrl.at(index);
|
||||
if (!control || !this.epgBridge.supportsFilePicker) {
|
||||
return;
|
||||
}
|
||||
const filePath = await this.epgBridge.pickEpgFile();
|
||||
if (!filePath) {
|
||||
return;
|
||||
}
|
||||
control.setValue(filePath);
|
||||
control.markAsDirty();
|
||||
control.markAsTouched();
|
||||
this.formFacade.form.markAsDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Force-fetch EPG for a single URL, bypassing the 12-hour freshness check.
|
||||
* The plain fetchEpg would short-circuit on fresh data and click the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { Settings, VideoPlayer } from '@iptvnator/shared/interfaces';
|
||||
import {
|
||||
createEpgUrlControl,
|
||||
createSettingsForm,
|
||||
createSettingsFromFormValue,
|
||||
} from './settings-form.utils';
|
||||
@@ -202,3 +203,24 @@ describe('settings form utils — embedded MPV session options', () => {
|
||||
expect(settings.embeddedMpvAutoReconnect).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings form utils — EPG source control', () => {
|
||||
it.each([
|
||||
'https://epg.example.org/guide.xml.gz',
|
||||
'/home/user/epg/guide.xml',
|
||||
'C:\\epg\\guide.xml.gz',
|
||||
'file:///home/user/epg/guide.xml',
|
||||
'',
|
||||
])('accepts %j', (value) => {
|
||||
expect(createEpgUrlControl(value).valid).toBe(true);
|
||||
});
|
||||
|
||||
it.each(['guide.xml', 'ftp://epg.example.org/guide.xml', 'epg'])(
|
||||
'rejects %j',
|
||||
(value) => {
|
||||
const control = createEpgUrlControl(value);
|
||||
expect(control.valid).toBe(false);
|
||||
expect(control.errors).toEqual({ epgSourceReference: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -23,11 +23,10 @@ import {
|
||||
StreamFormat,
|
||||
Theme,
|
||||
validateEmbeddedMpvExtraOptions,
|
||||
validateEpgSourceReferenceControl,
|
||||
VideoPlayer,
|
||||
} from '@iptvnator/shared/interfaces';
|
||||
|
||||
export const EPG_URL_PATTERN = /^(http|https|file):\/\/[^ "]+$/;
|
||||
|
||||
/**
|
||||
* Rejects malformed lines and the option keys the embed depends on, so a
|
||||
* value that the main process would have to drop never gets saved.
|
||||
@@ -44,8 +43,13 @@ export function embeddedMpvExtraOptionsValidator(
|
||||
return validateEmbeddedMpvExtraOptions(control.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* An EPG source is a remote XMLTV link or a local file (absolute path or
|
||||
* `file:` URL); the accepted shapes live in `@iptvnator/shared/interfaces`
|
||||
* so the playlist dialog validates identically.
|
||||
*/
|
||||
export function createEpgUrlControl(value = ''): FormControl<string | null> {
|
||||
return new FormControl(value, [Validators.pattern(EPG_URL_PATTERN)]);
|
||||
return new FormControl(value, [validateEpgSourceReferenceControl]);
|
||||
}
|
||||
|
||||
export function createSettingsForm(
|
||||
|
||||
@@ -40,8 +40,10 @@
|
||||
[form]="settingsForm"
|
||||
[epgUrl]="form.epgUrl"
|
||||
[isClearingEpgData]="epg.isClearing()"
|
||||
[canBrowseFiles]="epg.supportsFilePicker"
|
||||
[epgViewModeOptions]="epgViewModeOptions"
|
||||
(refreshEpg)="epg.refresh($event)"
|
||||
(browseEpgSource)="epg.browse($event)"
|
||||
(removeEpgSource)="form.removeEpgSource($event)"
|
||||
(addEpgSource)="form.addEpgSource()"
|
||||
(refreshAllEpg)="epg.refreshAll()"
|
||||
|
||||
@@ -303,6 +303,22 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.epg-sources__formats-examples {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 4px 8px;
|
||||
|
||||
code {
|
||||
padding: 1px 6px;
|
||||
border-radius: 6px;
|
||||
background: var(--app-hover-overlay);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.epg-sources-empty {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
@@ -216,7 +216,9 @@ export function createEpgBridgeStub(): Partial<EpgRuntimeBridgeService> {
|
||||
clearEpgData: jest.fn().mockResolvedValue({ success: true }),
|
||||
clearEpgDataForSource: jest.fn().mockResolvedValue({ success: true }),
|
||||
forceFetchEpg: jest.fn().mockResolvedValue({ success: true }),
|
||||
pickEpgFile: jest.fn().mockResolvedValue(null),
|
||||
supportsDataManagement: true,
|
||||
supportsFilePicker: true,
|
||||
supportsImport: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "تحديث EPG",
|
||||
"REFRESH_ALL_EPG": "تحديث الكل",
|
||||
"REMOVE_EPG_SOURCE": "إزالة مصدر EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "محدث",
|
||||
"EPG_STATUS_STALE": "يحتاج تحديث",
|
||||
"EPG_STATUS_ERROR": "فشل",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "فشل مسح بيانات EPG. يرجى المحاولة مرة أخرى.",
|
||||
"CLEARING_EPG_DATA": "جارٍ المسح…",
|
||||
"EPG_URL_ERROR": "القيمة ليست رابطًا صالحًا",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "اختر مشغل الفيديو الافتراضي",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "عناصر تحكم موحّدة لمشغلات الويب",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "استخدم عناصر التحكم المشتركة في IPTVnator مع HTML5 وVideo.js وArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "حدث EPG",
|
||||
"REFRESH_ALL_EPG": "حدث الكل",
|
||||
"REMOVE_EPG_SOURCE": "زول مصدر EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "محدث",
|
||||
"EPG_STATUS_STALE": "خاصو يتحدث",
|
||||
"EPG_STATUS_ERROR": "فشل",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "فشل مسح بيانات EPG. عفاك حاول مرة أخرى.",
|
||||
"CLEARING_EPG_DATA": "جاري المسح…",
|
||||
"EPG_URL_ERROR": "القيمة ماشي رابط صحيح",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "اختار مشغل الفيديو الافتراضي",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "عناصر تحكم موحدة لمشغلات الويب",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "استعمل عناصر التحكم المشتركة ديال IPTVnator مع HTML5 وVideo.js وArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "Абнавіць праграму каналаў (EPG)",
|
||||
"REFRESH_ALL_EPG": "Абнавіць усё",
|
||||
"REMOVE_EPG_SOURCE": "Выдаліць крыніцу EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Актуальна",
|
||||
"EPG_STATUS_STALE": "Патрабуе абнаўлення",
|
||||
"EPG_STATUS_ERROR": "Памылка",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Не ўдалося ачысціць дадзеныя EPG. Калі ласка, паспрабуйце яшчэ раз.",
|
||||
"CLEARING_EPG_DATA": "Ачышчаецца...",
|
||||
"EPG_URL_ERROR": "Уведзенае значэнне не з'яўляецца URL-адрасам.",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Выбраць стандартны відэапрайгравальнік",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Адзіныя элементы кіравання для вэб-прайгравальнікаў",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Выкарыстоўваць агульныя элементы кіравання IPTVnator у HTML5, Video.js і ArtPlayer.",
|
||||
|
||||
@@ -268,10 +268,10 @@
|
||||
"GENERAL_SUBTITLE": "Allgemeine App-Einstellungen ändern",
|
||||
"PLAYBACK": "Wiedergabe",
|
||||
"EPG_SOURCES": "EPG-Quellen",
|
||||
"EPG_SOURCES_DESCRIPTION": "Eine oder mehrere URLs als EPG-Quellen hinzufügen",
|
||||
"EPG_SOURCES_DESCRIPTION": "Eine oder mehrere XMLTV-Quellen hinzufügen: Links oder lokale Dateien",
|
||||
"PLAYLIST_EPG_SOURCES_AUTO_SELECTED": "{{enabled}} von {{detected}} erkannten EPG-Quellen der Wiedergabeliste wurden automatisch für den Import ausgewählt.",
|
||||
"EPG_EMPTY_TITLE": "Noch keine EPG-Quellen",
|
||||
"EPG_EMPTY_HINT": "Füge eine URL hinzu, um Programmdaten für deine Kanäle abzurufen.",
|
||||
"EPG_EMPTY_HINT": "Füge eine URL oder eine lokale XMLTV-Datei hinzu, um Programmdaten für deine Kanäle zu laden.",
|
||||
"PREFER_UPLOADED_EPG_TITLE": "Eigene EPG-Quellen bei Xtream-Playlists bevorzugen",
|
||||
"PREFER_UPLOADED_EPG_HINT": "Standardmäßig nutzen Xtream-Playlists die Programmdaten deines Anbieters, und dein hochgeladenes EPG füllt nur fehlende Kanäle. Aktiviere die Option, um stattdessen zuerst dein hochgeladenes EPG zu nutzen.",
|
||||
"DATA": "Daten",
|
||||
@@ -314,11 +314,12 @@
|
||||
"HERO_DESCRIPTION": "Passen Sie Wiedergabe, Programmführer, Fernzugriff und Datenverwaltung zentral an, ohne den Stil des Arbeitsbereichs zu verlieren.",
|
||||
"SUBTITLE": "Die App-Einstellungen ändern",
|
||||
"DESCRIPTION": "Bitte vergessen Sie nicht die Änderungen mit dem Speicher-Button zu bestätigen",
|
||||
"EPG_URL_LABEL": "TV-Programm (EPG) URL",
|
||||
"EPG_URL_PLACEHOLDER": "URL eingeben",
|
||||
"EPG_URL_LABEL": "EPG-Quelle (URL oder lokale Datei, *.xml oder *.xml.gz)",
|
||||
"EPG_URL_PLACEHOLDER": "URL oder Dateipfad eingeben",
|
||||
"REFRESH_EPG": "TV-Programm aktualisieren",
|
||||
"REFRESH_ALL_EPG": "Alle aktualisieren",
|
||||
"REMOVE_EPG_SOURCE": "EPG-Quelle entfernen",
|
||||
"BROWSE_EPG_FILE": "Lokale XMLTV-Datei auswählen…",
|
||||
"EPG_STATUS_FRESH": "Aktuell",
|
||||
"EPG_STATUS_STALE": "Aktualisierung nötig",
|
||||
"EPG_STATUS_ERROR": "Fehlgeschlagen",
|
||||
@@ -363,7 +364,10 @@
|
||||
"EPG_DATA_CLEARED": "EPG-Daten wurden gelöscht",
|
||||
"EPG_DATA_CLEAR_FAILED": "EPG-Daten konnten nicht gelöscht werden. Bitte erneut versuchen.",
|
||||
"CLEARING_EPG_DATA": "Wird gelöscht…",
|
||||
"EPG_URL_ERROR": "Der Wert ist keine gültige URL",
|
||||
"EPG_URL_ERROR": "Gib einen http(s)-Link, einen absoluten Dateipfad oder eine file://-URL ein",
|
||||
"EPG_SOURCE_LIST_TITLE": "Quellenliste",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Unterstützt werden XMLTV-Links (http/https) und Dateien auf diesem Computer, als einfaches .xml oder gzip-komprimiertes .xml.gz. Lokale Dateien brauchen einen absoluten Pfad oder eine file://-URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Beispiele:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Wählen Sie den Standard-Videoplayer aus",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Einheitliche Steuerung für Web-Player",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Verwendet die gemeinsamen IPTVnator-Steuerelemente in HTML5, Video.js und ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "Ανανέωση EPG",
|
||||
"REFRESH_ALL_EPG": "Ανανέωση όλων",
|
||||
"REMOVE_EPG_SOURCE": "Αφαίρεση πηγής EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Ενημερωμένο",
|
||||
"EPG_STATUS_STALE": "Χρειάζεται ανανέωση",
|
||||
"EPG_STATUS_ERROR": "Αποτυχία",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Αποτυχία διαγραφής δεδομένων EPG. Παρακαλώ δοκιμάστε ξανά.",
|
||||
"CLEARING_EPG_DATA": "Διαγραφή…",
|
||||
"EPG_URL_ERROR": "Η τιμή δεν είναι έγκυρη διεύθυνση URL",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Επιλογή προεπιλεγμένου προγράμματος αναπαραγωγής βίντεο",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Ενοποιημένα στοιχεία ελέγχου για web players",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Χρησιμοποιήστε τα κοινά στοιχεία ελέγχου του IPTVnator σε HTML5, Video.js και ArtPlayer.",
|
||||
|
||||
@@ -268,10 +268,10 @@
|
||||
"GENERAL_SUBTITLE": "Change the configuration of the application",
|
||||
"PLAYBACK": "Playback",
|
||||
"EPG_SOURCES": "EPG sources",
|
||||
"EPG_SOURCES_DESCRIPTION": "Add one or more URLs as EPG sources",
|
||||
"EPG_SOURCES_DESCRIPTION": "Add one or more XMLTV sources: remote links or local files",
|
||||
"PLAYLIST_EPG_SOURCES_AUTO_SELECTED": "{{enabled}} of {{detected}} detected playlist EPG sources were auto-selected for import.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels.",
|
||||
"EPG_EMPTY_HINT": "Add a URL or a local XMLTV file to fetch program data for your channels.",
|
||||
"PREFER_UPLOADED_EPG_TITLE": "Prefer your EPG sources for Xtream playlists",
|
||||
"PREFER_UPLOADED_EPG_HINT": "By default, Xtream playlists use the program guide from your provider, and your uploaded EPG only fills missing channels. Turn this on to use your uploaded EPG first instead.",
|
||||
"DATA": "Data",
|
||||
@@ -314,11 +314,12 @@
|
||||
"HERO_DESCRIPTION": "Tune playback, guides, remote access and data handling from one place without losing the current workspace style.",
|
||||
"SUBTITLE": "Change the configuration of the application",
|
||||
"DESCRIPTION": "Please adapt the options from the list below and confirm with the save changes button",
|
||||
"EPG_URL_LABEL": "EPG Url (*.xml or *.xml.gz)",
|
||||
"EPG_URL_PLACEHOLDER": "Enter an URL",
|
||||
"EPG_URL_LABEL": "EPG source (URL or local file, *.xml or *.xml.gz)",
|
||||
"EPG_URL_PLACEHOLDER": "Enter a URL or a local file path",
|
||||
"REFRESH_EPG": "Refresh EPG",
|
||||
"REFRESH_ALL_EPG": "Refresh all",
|
||||
"REMOVE_EPG_SOURCE": "Remove EPG source",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Up to date",
|
||||
"EPG_STATUS_STALE": "Needs refresh",
|
||||
"EPG_STATUS_ERROR": "Failed",
|
||||
@@ -363,7 +364,10 @@
|
||||
"EPG_DATA_CLEARED": "EPG data has been cleared",
|
||||
"EPG_DATA_CLEAR_FAILED": "Failed to clear EPG data. Please try again.",
|
||||
"CLEARING_EPG_DATA": "Clearing…",
|
||||
"EPG_URL_ERROR": "The value is not a valid URL",
|
||||
"EPG_URL_ERROR": "Enter an http(s) link, an absolute file path or a file:// URL",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Select default video player",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Unified controls for web players",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Use IPTVnator's shared controls in HTML5, Video.js, and ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "Actualizar EPG",
|
||||
"REFRESH_ALL_EPG": "Actualizar todo",
|
||||
"REMOVE_EPG_SOURCE": "Eliminar fuente EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Actualizado",
|
||||
"EPG_STATUS_STALE": "Necesita actualización",
|
||||
"EPG_STATUS_ERROR": "Error",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "No se pudieron borrar los datos EPG. Inténtalo de nuevo.",
|
||||
"CLEARING_EPG_DATA": "Borrando…",
|
||||
"EPG_URL_ERROR": "El valor no es una URL válida.",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Seleccionar reproductor de vídeo predeterminado",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Controles unificados para reproductores web",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Usa los controles compartidos de IPTVnator en HTML5, Video.js y ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "Mise à jour de l'EPG",
|
||||
"REFRESH_ALL_EPG": "Tout actualiser",
|
||||
"REMOVE_EPG_SOURCE": "Supprimer la source EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "À jour",
|
||||
"EPG_STATUS_STALE": "À actualiser",
|
||||
"EPG_STATUS_ERROR": "Échec",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Échec de l'effacement des données EPG. Veuillez réessayer.",
|
||||
"CLEARING_EPG_DATA": "Effacement…",
|
||||
"EPG_URL_ERROR": "La valeur n'est pas une URL valide",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Sélectionnez le lecteur vidéo par défaut",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Commandes unifiées pour les lecteurs web",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Utilise les commandes partagées d’IPTVnator dans HTML5, Video.js et ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "EPG frissítése",
|
||||
"REFRESH_ALL_EPG": "Összes frissítése",
|
||||
"REMOVE_EPG_SOURCE": "EPG-forrás eltávolítása",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Naprakész",
|
||||
"EPG_STATUS_STALE": "Frissítendő",
|
||||
"EPG_STATUS_ERROR": "Sikertelen",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Nem sikerült törölni az EPG-adatokat. Próbálja újra.",
|
||||
"CLEARING_EPG_DATA": "Törlés…",
|
||||
"EPG_URL_ERROR": "A megadott érték nem érvényes URL-cím",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Az alapértelmezett videólejátszó kiválasztása",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Egységes vezérlők a webes lejátszókhoz",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Az IPTVnator közös vezérlőinek használata a HTML5-, Video.js- és ArtPlayer-lejátszóban.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "Aggiorna EPG",
|
||||
"REFRESH_ALL_EPG": "Aggiorna tutto",
|
||||
"REMOVE_EPG_SOURCE": "Rimuovi sorgente EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Aggiornato",
|
||||
"EPG_STATUS_STALE": "Da aggiornare",
|
||||
"EPG_STATUS_ERROR": "Errore",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Impossibile cancellare i dati EPG. Riprova.",
|
||||
"CLEARING_EPG_DATA": "Cancellazione…",
|
||||
"EPG_URL_ERROR": "Il valore non è una URL valida",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Seleziona lettore video predefinito",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Controlli unificati per i player web",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Usa i controlli condivisi di IPTVnator in HTML5, Video.js e ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "EPGを更新",
|
||||
"REFRESH_ALL_EPG": "すべて更新",
|
||||
"REMOVE_EPG_SOURCE": "EPGソースを削除",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "最新",
|
||||
"EPG_STATUS_STALE": "更新が必要",
|
||||
"EPG_STATUS_ERROR": "失敗",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "EPGデータのクリアに失敗しました。もう一度お試しください。",
|
||||
"CLEARING_EPG_DATA": "クリア中…",
|
||||
"EPG_URL_ERROR": "有効なURLではありません",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "デフォルトのビデオプレーヤーを選択",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Webプレーヤーの統一コントロール",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "HTML5、Video.js、ArtPlayerでIPTVnator共通のコントロールを使用します。",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "EPG 새로 고침",
|
||||
"REFRESH_ALL_EPG": "모두 새로 고침",
|
||||
"REMOVE_EPG_SOURCE": "EPG 소스 제거",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "최신",
|
||||
"EPG_STATUS_STALE": "새로 고침 필요",
|
||||
"EPG_STATUS_ERROR": "실패",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "EPG 데이터를 지우지 못했습니다. 다시 시도해 주세요.",
|
||||
"CLEARING_EPG_DATA": "지우는 중…",
|
||||
"EPG_URL_ERROR": "값이 유효한 URL이 아닙니다.",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "기본 비디오 플레이어 선택",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "웹 플레이어 통합 컨트롤",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "HTML5, Video.js 및 ArtPlayer에서 IPTVnator 공통 컨트롤을 사용합니다.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "EPG vernieuwen",
|
||||
"REFRESH_ALL_EPG": "Alles vernieuwen",
|
||||
"REMOVE_EPG_SOURCE": "EPG-bron verwijderen",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Up-to-date",
|
||||
"EPG_STATUS_STALE": "Verouderd",
|
||||
"EPG_STATUS_ERROR": "Mislukt",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Wissen van EPG-gegevens mislukt. Probeer het opnieuw.",
|
||||
"CLEARING_EPG_DATA": "Wissen…",
|
||||
"EPG_URL_ERROR": "De opgegeven waarde is geen geldige URL.",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Selecteer de standaard videospeler",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Uniforme bediening voor webspelers",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Gebruik de gedeelde IPTVnator-bediening in HTML5, Video.js en ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "Odśwież EPG",
|
||||
"REFRESH_ALL_EPG": "Odśwież wszystko",
|
||||
"REMOVE_EPG_SOURCE": "Usuń źródło EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Aktualne",
|
||||
"EPG_STATUS_STALE": "Wymaga odświeżenia",
|
||||
"EPG_STATUS_ERROR": "Błąd",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Nie udało się wyczyścić danych EPG. Spróbuj ponownie.",
|
||||
"CLEARING_EPG_DATA": "Czyszczenie…",
|
||||
"EPG_URL_ERROR": "Wartość nie jest prawidłowym URL",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Wybierz domyślny odtwarzacz wideo",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Ujednolicone sterowanie odtwarzaczami internetowymi",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Używaj wspólnych elementów sterowania IPTVnator w HTML5, Video.js i ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "Atualizar EPG",
|
||||
"REFRESH_ALL_EPG": "Atualizar tudo",
|
||||
"REMOVE_EPG_SOURCE": "Remover fonte EPG",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Atualizado",
|
||||
"EPG_STATUS_STALE": "Necessita atualização",
|
||||
"EPG_STATUS_ERROR": "Falha",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "Falha ao limpar os dados de EPG. Tente novamente.",
|
||||
"CLEARING_EPG_DATA": "Limpando…",
|
||||
"EPG_URL_ERROR": "O valor não é uma URL válida",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Selecionar reprodutor de vídeo padrão",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Controlos unificados para leitores web",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Usa os controlos partilhados do IPTVnator em HTML5, Video.js e ArtPlayer.",
|
||||
|
||||
@@ -268,10 +268,10 @@
|
||||
"GENERAL_SUBTITLE": "Изменение основных параметров приложения",
|
||||
"PLAYBACK": "Воспроизведение",
|
||||
"EPG_SOURCES": "Источники EPG",
|
||||
"EPG_SOURCES_DESCRIPTION": "Добавьте один или несколько URL-адресов источников EPG",
|
||||
"EPG_SOURCES_DESCRIPTION": "Добавьте один или несколько источников XMLTV: ссылки или локальные файлы",
|
||||
"PLAYLIST_EPG_SOURCES_AUTO_SELECTED": "{{enabled}} из {{detected}} обнаруженных источников EPG плейлиста были автоматически выбраны для импорта.",
|
||||
"EPG_EMPTY_TITLE": "Источников EPG пока нет",
|
||||
"EPG_EMPTY_HINT": "Добавьте URL, чтобы получить программу передач для каналов.",
|
||||
"EPG_EMPTY_HINT": "Добавьте ссылку или локальный XMLTV-файл, чтобы получить программу передач для каналов.",
|
||||
"PREFER_UPLOADED_EPG_TITLE": "Предпочитать ваши источники EPG для плейлистов Xtream",
|
||||
"PREFER_UPLOADED_EPG_HINT": "По умолчанию плейлисты Xtream используют программу передач от вашего провайдера, а ваши источники EPG заполняют только недостающие каналы. Включите, чтобы сначала использовать ваш загруженный EPG.",
|
||||
"DATA": "Данные",
|
||||
@@ -314,11 +314,12 @@
|
||||
"HERO_DESCRIPTION": "Настраивайте воспроизведение, телегид, удалённый доступ и работу с данными в одном месте, не теряя стиль текущего рабочего пространства.",
|
||||
"SUBTITLE": "Здесь можно изменить общие настройки приложения",
|
||||
"DESCRIPTION": "Закончив настройку, не забудьте подтвердить новые настройки кнопкой 'Сохранить'",
|
||||
"EPG_URL_LABEL": "Ссылка на программу каналов (EPG) (*.xml или *.xml.gz)",
|
||||
"EPG_URL_PLACEHOLDER": "Введите ссылку",
|
||||
"EPG_URL_LABEL": "Источник EPG (ссылка или локальный файл, *.xml или *.xml.gz)",
|
||||
"EPG_URL_PLACEHOLDER": "Введите ссылку или путь к файлу",
|
||||
"REFRESH_EPG": "Обновить программу каналов (EPG)",
|
||||
"REFRESH_ALL_EPG": "Обновить все",
|
||||
"REMOVE_EPG_SOURCE": "Удалить источник EPG",
|
||||
"BROWSE_EPG_FILE": "Выбрать локальный XMLTV-файл…",
|
||||
"EPG_STATUS_FRESH": "Актуально",
|
||||
"EPG_STATUS_STALE": "Требует обновления",
|
||||
"EPG_STATUS_ERROR": "Ошибка",
|
||||
@@ -363,7 +364,10 @@
|
||||
"EPG_DATA_CLEARED": "Данные EPG очищены",
|
||||
"EPG_DATA_CLEAR_FAILED": "Не удалось очистить данные EPG. Попробуйте ещё раз.",
|
||||
"CLEARING_EPG_DATA": "Очистка…",
|
||||
"EPG_URL_ERROR": "Введенное значение не является URL-адресом.",
|
||||
"EPG_URL_ERROR": "Введите ссылку http(s), абсолютный путь к файлу или URL вида file://",
|
||||
"EPG_SOURCE_LIST_TITLE": "Список источников",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Поддерживаются как ссылки на XMLTV (http/https), так и файлы на этом компьютере, в виде обычного .xml или сжатого .xml.gz. Для локального файла укажите абсолютный путь или URL вида file://.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Примеры:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Выбрать стандартный видео плеер",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Единые элементы управления для веб-плееров",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Использовать общие элементы управления IPTVnator в HTML5, Video.js и ArtPlayer.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "EPG'yi yenile",
|
||||
"REFRESH_ALL_EPG": "Tümünü yenile",
|
||||
"REMOVE_EPG_SOURCE": "EPG kaynağını kaldır",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "Güncel",
|
||||
"EPG_STATUS_STALE": "Yenilenmeli",
|
||||
"EPG_STATUS_ERROR": "Başarısız",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "EPG verileri temizlenemedi. Lütfen tekrar deneyin.",
|
||||
"CLEARING_EPG_DATA": "Temizleniyor…",
|
||||
"EPG_URL_ERROR": "Girilen değer geçerli bir URL değildir",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "Varsayılan video oynatıcıyı seçin",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Web oynatıcıları için birleşik kontroller",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "HTML5, Video.js ve ArtPlayer'da IPTVnator'ın ortak kontrollerini kullan.",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "刷新电子节目单EPG",
|
||||
"REFRESH_ALL_EPG": "全部刷新",
|
||||
"REMOVE_EPG_SOURCE": "移除 EPG 源",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "已更新",
|
||||
"EPG_STATUS_STALE": "需要刷新",
|
||||
"EPG_STATUS_ERROR": "失败",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "清除 EPG 数据失败。请重试。",
|
||||
"CLEARING_EPG_DATA": "清除中…",
|
||||
"EPG_URL_ERROR": "该值不是有效的 URL",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "选择默认视频播放器",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Web 播放器统一控件",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "在 HTML5、Video.js 和 ArtPlayer 中使用 IPTVnator 的共享控件。",
|
||||
|
||||
@@ -319,6 +319,7 @@
|
||||
"REFRESH_EPG": "重新整理 EPG",
|
||||
"REFRESH_ALL_EPG": "全部重新整理",
|
||||
"REMOVE_EPG_SOURCE": "移除 EPG 來源",
|
||||
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
|
||||
"EPG_STATUS_FRESH": "已更新",
|
||||
"EPG_STATUS_STALE": "需要重新整理",
|
||||
"EPG_STATUS_ERROR": "失敗",
|
||||
@@ -364,6 +365,9 @@
|
||||
"EPG_DATA_CLEAR_FAILED": "清除 EPG 資料失敗。請重試。",
|
||||
"CLEARING_EPG_DATA": "正在清除…",
|
||||
"EPG_URL_ERROR": "該值不是有效的網址",
|
||||
"EPG_SOURCE_LIST_TITLE": "Source list",
|
||||
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
|
||||
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
|
||||
"VIDEO_PLAYER_DESCRIPTION": "選擇預設影片播放器",
|
||||
"WEB_PLAYER_SHARED_CONTROLS": "Web 播放器統一控制項",
|
||||
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "在 HTML5、Video.js 和 ArtPlayer 中使用 IPTVnator 的共用控制項。",
|
||||
|
||||
Reference in new issue
Block a user