feat: manual EPG-to-channel mapping with mapping fallback (#1165)

* feat(epg): manual EPG-to-channel mapping with mapping fallback in all EPG paths

* fix: epg mapping in live tv list

* fix(epg): harden manual EPG mapping — upgrade safety, perf, playlist-scoped keys

Follow-up fixes on top of the manual EPG-to-channel mapping feature:

- epg-database: dedupe existing epg_programs rows before creating the
  unique (channel_id, start, title) index — a plain CREATE UNIQUE INDEX
  crashed the EPG worker on upgrade when historical duplicates exist;
  replace INSERT OR REPLACE with ON CONFLICT DO UPDATE so the
  epg_programs_fts delete trigger is not bypassed (REPLACE skips delete
  triggers unless recursive_triggers is on), with a plain-INSERT
  fallback when the index cannot be created
- db: add idx_content_epg_channel — the mapping fallback scanned the
  whole content table on every single-channel EPG lookup
- keys: scope Xtream mapping keys per playlist via shared
  buildXtreamEpgMappingKey (xtream:{playlistId}:{id}) — bare stream ids
  collide across portals; the backend fallback now joins categories to
  resolve the playlist id
- pwa: hide "Map EPG channel" entries behind the supportsEpgMapping
  capability — the menu item was a dead end in the PWA
- parser: parse the XMLTV offset sign from the string — Math.sign(0)
  dropped the minutes of ±00:xx offsets
- cleanup: typed window.electron access instead of ad-hoc casts, drop
  unused resolveChannelId and dialog data field, shared
  EpgMappingDialogComponent.open() for all seven call sites
- dialog UX: minimum-characters search hint, save/remove snackbars,
  current mapping shows the EPG channel display name,
  takeUntilDestroyed on the search stream
- i18n: fill the new keys in all 17 locales
- tests: cover mapping CRUD/search escaping, the dedup-index guard,
  offset parsing and playlist-scoped keys; update stale stream-resolver
  specs for the new 50-item limit and 10s timeout

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(epg): escape backslashes in EPG channel search LIKE pattern

CodeQL js/incomplete-sanitization: a lone trailing backslash in the
search term paired with the closing wildcard under the ESCAPE clause
and corrupted the pattern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* perf(epg): batch mapping lookups in the viewport preview queue

Expose the existing getEpgMappingsBatch operation over a new
EPG_MAPPING_GET_BATCH IPC channel and use it in resolveManualMappings —
the per-entry lookup issued one IPC round-trip per visible channel on
every scroll event.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* perf(epg): batch mapping prefetch in the collection preview loader

Resolve all candidate mapping keys for an Xtream preview batch with a
single getEpgMappingsBatch IPC call instead of per-channel lookups.
Also fix a worker early-exit: a channel without tvgId/name returned out
of the shared-iterator loop and silently killed one of the three
concurrent preview workers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: 4gray <serega05@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-07-19 09:00:14 +02:00
1 parent 45b6d8a041
commit ec6fc403a3
60 files changed
+2343 -91

No files matched your search

+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "إزالة من المفضلة",
"ADD_FAVORITE": "إضافة إلى المفضلة",
"SHOW_DETAILS": "عرض تفاصيل القناة",
"MAP_EPG": "ربط قناة دليل البرامج",
"FAVORITES_UPDATED": "تم تحديث المفضلة!",
"SELECT_CHANNEL_PLAYBACK": "يرجى اختيار قناة لبدء التشغيل",
"SORT_BY": "ترتيب حسب",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "عرض ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "ربط قناة دليل البرامج (EPG)",
"SUBTITLE": "اختر يدويًا قناة دليل البرامج لـ \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "البحث في قنوات دليل البرامج...",
"CURRENT_MAPPING": "الربط الحالي",
"NO_MAPPING": "لم يتم تعيين ربط لدليل البرامج",
"SAVE": "حفظ الربط",
"REMOVE": "إزالة الربط",
"CLOSE": "إغلاق",
"NO_RESULTS": "لم يتم العثور على قنوات دليل البرامج",
"SEARCH_HINT": "اكتب {{min}} أحرف على الأقل للبحث",
"SAVED": "تم حفظ ربط دليل البرامج",
"REMOVED": "تمت إزالة ربط دليل البرامج",
"SAVE_FAILED": "تعذر تحديث ربط دليل البرامج"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "حيد من المفضلة",
"ADD_FAVORITE": "زيد للمفضلة",
"SHOW_DETAILS": "وري تفاصيل القناة",
"MAP_EPG": "ربط قناة ديال EPG",
"FAVORITES_UPDATED": "المفضلة تحدثات!",
"SELECT_CHANNEL_PLAYBACK": "عفاك اختار قناة باش يبدا التشغيل",
"SORT_BY": "رتب بـ",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "وري ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "ربط قناة ديال EPG",
"SUBTITLE": "اختار يدويا قناة EPG لـ \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "قلب على قنوات EPG...",
"CURRENT_MAPPING": "الربط الحالي",
"NO_MAPPING": "ما كاين حتى ربط ديال EPG",
"SAVE": "سجل الربط",
"REMOVE": "حيد الربط",
"CLOSE": "سد",
"NO_RESULTS": "ما لقينا حتى قناة EPG",
"SEARCH_HINT": "كتب على الأقل {{min}} حروف باش تقلب",
"SAVED": "تسجل الربط ديال EPG",
"REMOVED": "تحيد الربط ديال EPG",
"SAVE_FAILED": "ما قدرناش نبدلو الربط ديال EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Выдаліць са спісу фаварытаў",
"ADD_FAVORITE": "Дадаць у выбранае",
"SHOW_DETAILS": "Паказаць інфармацыю аб канале",
"MAP_EPG": "Прывязаць канал EPG",
"FAVORITES_UPDATED": "Спіс фаварытаў быў абноўлены!",
"SELECT_CHANNEL_PLAYBACK": "Калі ласка, выберыце канал, каб пачаць прайграванне",
"SORT_BY": "Сартаваць па",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "паказаць ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Прывязка канала EPG",
"SUBTITLE": "Выберыце канал EPG для \"{{channelName}}\" уручную",
"SEARCH_PLACEHOLDER": "Пошук каналаў EPG...",
"CURRENT_MAPPING": "Бягучая прывязка",
"NO_MAPPING": "Прывязка EPG не зададзена",
"SAVE": "Захаваць прывязку",
"REMOVE": "Выдаліць прывязку",
"CLOSE": "Закрыць",
"NO_RESULTS": "Каналы EPG не знойдзены",
"SEARCH_HINT": "Увядзіце не менш за {{min}} сімвалы для пошуку",
"SAVED": "Прывязка EPG захавана",
"REMOVED": "Прывязка EPG выдалена",
"SAVE_FAILED": "Не ўдалося абнавіць прывязку EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Aus Favoritenliste entfernen",
"ADD_FAVORITE": "Zu Favoriten hinzufügen",
"SHOW_DETAILS": "Senderdetails anzeigen",
"MAP_EPG": "EPG-Kanal zuordnen",
"FAVORITES_UPDATED": "Favoriten wurden aktualisiert!",
"SELECT_CHANNEL_PLAYBACK": "Bitte wählen Sie einen Sender aus, um die Wiedergabe zu starten",
"SORT_BY": "Sortieren nach",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "anzeigen ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "EPG-Kanal zuordnen",
"SUBTITLE": "EPG-Kanal für \"{{channelName}}\" manuell auswählen",
"SEARCH_PLACEHOLDER": "EPG-Kanäle durchsuchen...",
"CURRENT_MAPPING": "Aktuelle Zuordnung",
"NO_MAPPING": "Keine EPG-Zuordnung festgelegt",
"SAVE": "Zuordnung speichern",
"REMOVE": "Zuordnung entfernen",
"CLOSE": "Schließen",
"NO_RESULTS": "Keine EPG-Kanäle gefunden",
"SEARCH_HINT": "Mindestens {{min}} Zeichen zum Suchen eingeben",
"SAVED": "EPG-Zuordnung gespeichert",
"REMOVED": "EPG-Zuordnung entfernt",
"SAVE_FAILED": "EPG-Zuordnung konnte nicht aktualisiert werden"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Αφαίρεση από τα αγαπημένα",
"ADD_FAVORITE": "Προσθήκη στα αγαπημένα",
"SHOW_DETAILS": "Εμφάνιση λεπτομερειών καναλιού",
"MAP_EPG": "Αντιστοίχιση καναλιού EPG",
"FAVORITES_UPDATED": "Τα αγαπημένα ενημερώθηκαν!",
"SELECT_CHANNEL_PLAYBACK": "Επιλέξτε ένα κανάλι για να ξεκινήσει η αναπαραγωγή",
"SORT_BY": "Ταξινόμηση κατά",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "εμφάνιση ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Αντιστοίχιση καναλιού EPG",
"SUBTITLE": "Επιλέξτε χειροκίνητα κανάλι EPG για το \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "Αναζήτηση καναλιών EPG...",
"CURRENT_MAPPING": "Τρέχουσα αντιστοίχιση",
"NO_MAPPING": "Δεν έχει οριστεί αντιστοίχιση EPG",
"SAVE": "Αποθήκευση αντιστοίχισης",
"REMOVE": "Κατάργηση αντιστοίχισης",
"CLOSE": "Κλείσιμο",
"NO_RESULTS": "Δεν βρέθηκαν κανάλια EPG",
"SEARCH_HINT": "Πληκτρολογήστε τουλάχιστον {{min}} χαρακτήρες για αναζήτηση",
"SAVED": "Η αντιστοίχιση EPG αποθηκεύτηκε",
"REMOVED": "Η αντιστοίχιση EPG καταργήθηκε",
"SAVE_FAILED": "Δεν ήταν δυνατή η ενημέρωση της αντιστοίχισης EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Remove from favorites",
"ADD_FAVORITE": "Add to favorites",
"SHOW_DETAILS": "Show channel details",
"MAP_EPG": "Map EPG channel",
"FAVORITES_UPDATED": "Favorites were updated!",
"SELECT_CHANNEL_PLAYBACK": "Please select a channel to start playback",
"SORT_BY": "Sort by",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "show ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Map EPG Channel",
"SUBTITLE": "Manually select an EPG channel for \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "Search EPG channels...",
"CURRENT_MAPPING": "Current mapping",
"NO_MAPPING": "No EPG mapping set",
"SAVE": "Save mapping",
"REMOVE": "Remove mapping",
"CLOSE": "Close",
"NO_RESULTS": "No EPG channels found",
"SEARCH_HINT": "Type at least {{min}} characters to search",
"SAVED": "EPG mapping saved",
"REMOVED": "EPG mapping removed",
"SAVE_FAILED": "Could not update the EPG mapping"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Quitar de favoritos",
"ADD_FAVORITE": "Agregar a favoritos",
"SHOW_DETAILS": "Mostrar detalles del canal",
"MAP_EPG": "Asignar canal EPG",
"FAVORITES_UPDATED": "¡Se actualizaron los favoritos!",
"SELECT_CHANNEL_PLAYBACK": "Selecciona un canal para iniciar la reproducción",
"SORT_BY": "Ordenar por",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "ver ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Asignar canal EPG",
"SUBTITLE": "Selecciona manualmente un canal EPG para \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "Buscar canales EPG...",
"CURRENT_MAPPING": "Asignación actual",
"NO_MAPPING": "No hay asignación EPG",
"SAVE": "Guardar asignación",
"REMOVE": "Eliminar asignación",
"CLOSE": "Cerrar",
"NO_RESULTS": "No se encontraron canales EPG",
"SEARCH_HINT": "Escribe al menos {{min}} caracteres para buscar",
"SAVED": "Asignación EPG guardada",
"REMOVED": "Asignación EPG eliminada",
"SAVE_FAILED": "No se pudo actualizar la asignación EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Retirer des favoris",
"ADD_FAVORITE": "Ajouter aux favoris",
"SHOW_DETAILS": "Afficher les détails de la chaîne",
"MAP_EPG": "Associer une chaîne EPG",
"FAVORITES_UPDATED": "Les favoris ont été mis à jour !",
"SELECT_CHANNEL_PLAYBACK": "Veuillez sélectionner une chaîne pour démarrer la lecture",
"SORT_BY": "Trier par",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "afficher ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Associer une chaîne EPG",
"SUBTITLE": "Sélectionner manuellement une chaîne EPG pour « {{channelName}} »",
"SEARCH_PLACEHOLDER": "Rechercher des chaînes EPG...",
"CURRENT_MAPPING": "Association actuelle",
"NO_MAPPING": "Aucune association EPG définie",
"SAVE": "Enregistrer l'association",
"REMOVE": "Supprimer l'association",
"CLOSE": "Fermer",
"NO_RESULTS": "Aucune chaîne EPG trouvée",
"SEARCH_HINT": "Saisissez au moins {{min}} caractères pour rechercher",
"SAVED": "Association EPG enregistrée",
"REMOVED": "Association EPG supprimée",
"SAVE_FAILED": "Impossible de mettre à jour l'association EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Rimuovi dai preferiti",
"ADD_FAVORITE": "Aggiungi ai preferiti",
"SHOW_DETAILS": "Mostra dettagli canale",
"MAP_EPG": "Associa canale EPG",
"FAVORITES_UPDATED": "Aggiornamento preferiti completato!",
"SELECT_CHANNEL_PLAYBACK": "Seleziona un canale per avviare la riproduzione",
"SORT_BY": "Ordina per",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "mostra ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Associa canale EPG",
"SUBTITLE": "Seleziona manualmente un canale EPG per \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "Cerca canali EPG...",
"CURRENT_MAPPING": "Associazione attuale",
"NO_MAPPING": "Nessuna associazione EPG impostata",
"SAVE": "Salva associazione",
"REMOVE": "Rimuovi associazione",
"CLOSE": "Chiudi",
"NO_RESULTS": "Nessun canale EPG trovato",
"SEARCH_HINT": "Digita almeno {{min}} caratteri per cercare",
"SAVED": "Associazione EPG salvata",
"REMOVED": "Associazione EPG rimossa",
"SAVE_FAILED": "Impossibile aggiornare l'associazione EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "お気に入りから削除",
"ADD_FAVORITE": "お気に入りに追加",
"SHOW_DETAILS": "チャンネルの詳細を表示",
"MAP_EPG": "EPGチャンネルを割り当て",
"FAVORITES_UPDATED": "お気に入りが更新されました!",
"SELECT_CHANNEL_PLAYBACK": "再生を開始するチャンネルを選択してください",
"SORT_BY": "並び替え",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "表示 ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "EPGチャンネルの割り当て",
"SUBTITLE": "「{{channelName}}」のEPGチャンネルを手動で選択します",
"SEARCH_PLACEHOLDER": "EPGチャンネルを検索...",
"CURRENT_MAPPING": "現在の割り当て",
"NO_MAPPING": "EPGの割り当てはありません",
"SAVE": "割り当てを保存",
"REMOVE": "割り当てを削除",
"CLOSE": "閉じる",
"NO_RESULTS": "EPGチャンネルが見つかりません",
"SEARCH_HINT": "検索するには{{min}}文字以上入力してください",
"SAVED": "EPGの割り当てを保存しました",
"REMOVED": "EPGの割り当てを削除しました",
"SAVE_FAILED": "EPGの割り当てを更新できませんでした"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "즐겨찾기에서 삭제하기",
"ADD_FAVORITE": "즐겨찾기에 추가",
"SHOW_DETAILS": "채널 세부정보 표시",
"MAP_EPG": "EPG 채널 매핑",
"FAVORITES_UPDATED": "즐겨찾기가 업데이트되었습니다!",
"SELECT_CHANNEL_PLAYBACK": "재생을 시작할 채널을 선택하세요",
"SORT_BY": "정렬 기준",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "보기 ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "EPG 채널 매핑",
"SUBTITLE": "\"{{channelName}}\"의 EPG 채널을 직접 선택하세요",
"SEARCH_PLACEHOLDER": "EPG 채널 검색...",
"CURRENT_MAPPING": "현재 매핑",
"NO_MAPPING": "설정된 EPG 매핑 없음",
"SAVE": "매핑 저장",
"REMOVE": "매핑 제거",
"CLOSE": "닫기",
"NO_RESULTS": "EPG 채널을 찾을 수 없음",
"SEARCH_HINT": "검색하려면 {{min}}자 이상 입력하세요",
"SAVED": "EPG 매핑이 저장되었습니다",
"REMOVED": "EPG 매핑이 제거되었습니다",
"SAVE_FAILED": "EPG 매핑을 업데이트할 수 없습니다"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Verwijder uit favorieten",
"ADD_FAVORITE": "Toevoegen aan favorieten",
"SHOW_DETAILS": "Toon kanaaldetails",
"MAP_EPG": "EPG-kanaal koppelen",
"FAVORITES_UPDATED": "Favorieten zijn bijgewerkt!",
"SELECT_CHANNEL_PLAYBACK": "Selecteer een kanaal om af te spelen",
"SORT_BY": "Sorteren op",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "toon ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "EPG-kanaal koppelen",
"SUBTITLE": "Selecteer handmatig een EPG-kanaal voor \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "EPG-kanalen zoeken...",
"CURRENT_MAPPING": "Huidige koppeling",
"NO_MAPPING": "Geen EPG-koppeling ingesteld",
"SAVE": "Koppeling opslaan",
"REMOVE": "Koppeling verwijderen",
"CLOSE": "Sluiten",
"NO_RESULTS": "Geen EPG-kanalen gevonden",
"SEARCH_HINT": "Typ minimaal {{min}} tekens om te zoeken",
"SAVED": "EPG-koppeling opgeslagen",
"REMOVED": "EPG-koppeling verwijderd",
"SAVE_FAILED": "Kan de EPG-koppeling niet bijwerken"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Usuń z ulubionych",
"ADD_FAVORITE": "Dodaj do ulubionych",
"SHOW_DETAILS": "Pokaż szczegóły kanału",
"MAP_EPG": "Przypisz kanał EPG",
"FAVORITES_UPDATED": "Ulubione zostały zaktualizowane!",
"SELECT_CHANNEL_PLAYBACK": "Wybierz kanał, aby rozpocząć odtwarzanie",
"SORT_BY": "Sortuj według",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "pokaż ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Przypisz kanał EPG",
"SUBTITLE": "Ręcznie wybierz kanał EPG dla \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "Szukaj kanałów EPG...",
"CURRENT_MAPPING": "Bieżące przypisanie",
"NO_MAPPING": "Brak przypisania EPG",
"SAVE": "Zapisz przypisanie",
"REMOVE": "Usuń przypisanie",
"CLOSE": "Zamknij",
"NO_RESULTS": "Nie znaleziono kanałów EPG",
"SEARCH_HINT": "Wpisz co najmniej {{min}} znaki, aby wyszukać",
"SAVED": "Przypisanie EPG zapisane",
"REMOVED": "Przypisanie EPG usunięte",
"SAVE_FAILED": "Nie udało się zaktualizować przypisania EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Remover dos favoritos",
"ADD_FAVORITE": "Adicionar aos favoritos",
"SHOW_DETAILS": "Mostrar detalhes do canal",
"MAP_EPG": "Associar canal EPG",
"FAVORITES_UPDATED": "Favoritos foram atualizados!",
"SELECT_CHANNEL_PLAYBACK": "Selecione um canal para iniciar a reprodução",
"SORT_BY": "Ordenar por",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "mostrar ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Associar canal EPG",
"SUBTITLE": "Selecione manualmente um canal EPG para \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "Pesquisar canais EPG...",
"CURRENT_MAPPING": "Associação atual",
"NO_MAPPING": "Nenhuma associação EPG definida",
"SAVE": "Guardar associação",
"REMOVE": "Remover associação",
"CLOSE": "Fechar",
"NO_RESULTS": "Nenhum canal EPG encontrado",
"SEARCH_HINT": "Digite pelo menos {{min}} caracteres para pesquisar",
"SAVED": "Associação EPG guardada",
"REMOVED": "Associação EPG removida",
"SAVE_FAILED": "Não foi possível atualizar a associação EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Удалить из списка фаворитов",
"ADD_FAVORITE": "Добавить в избранное",
"SHOW_DETAILS": "Показать сведения о канале",
"MAP_EPG": "Привязать канал EPG",
"FAVORITES_UPDATED": "Список фаворитов был обновлен!",
"SELECT_CHANNEL_PLAYBACK": "Пожалуйста, выберите канал для начала воспроизведения",
"SORT_BY": "Сортировать по",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "показать ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Привязка канала EPG",
"SUBTITLE": "Выберите канал EPG для \"{{channelName}}\" вручную",
"SEARCH_PLACEHOLDER": "Поиск каналов EPG...",
"CURRENT_MAPPING": "Текущая привязка",
"NO_MAPPING": "Привязка EPG не задана",
"SAVE": "Сохранить привязку",
"REMOVE": "Удалить привязку",
"CLOSE": "Закрыть",
"NO_RESULTS": "Каналы EPG не найдены",
"SEARCH_HINT": "Введите не менее {{min}} символов для поиска",
"SAVED": "Привязка EPG сохранена",
"REMOVED": "Привязка EPG удалена",
"SAVE_FAILED": "Не удалось обновить привязку EPG"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "Favorilerden kaldır",
"ADD_FAVORITE": "Favorilere ekle",
"SHOW_DETAILS": "Kanal ayrıntılarını göster",
"MAP_EPG": "EPG kanalı eşle",
"FAVORITES_UPDATED": "Favoriler güncellendi!",
"SELECT_CHANNEL_PLAYBACK": "Lütfen oynatmaya başlamak için bir kanal seçin",
"SORT_BY": "Sırala",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "göster ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "EPG Kanalı Eşle",
"SUBTITLE": "\"{{channelName}}\" için EPG kanalını elle seçin",
"SEARCH_PLACEHOLDER": "EPG kanallarında ara...",
"CURRENT_MAPPING": "Geçerli eşleme",
"NO_MAPPING": "EPG eşlemesi ayarlanmadı",
"SAVE": "Eşlemeyi kaydet",
"REMOVE": "Eşlemeyi kaldır",
"CLOSE": "Kapat",
"NO_RESULTS": "EPG kanalı bulunamadı",
"SEARCH_HINT": "Aramak için en az {{min}} karakter yazın",
"SAVED": "EPG eşlemesi kaydedildi",
"REMOVED": "EPG eşlemesi kaldırıldı",
"SAVE_FAILED": "EPG eşlemesi güncellenemedi"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "从收藏夹中删除",
"ADD_FAVORITE": "添加到收藏",
"SHOW_DETAILS": "显示频道详情",
"MAP_EPG": "映射 EPG 频道",
"FAVORITES_UPDATED": "收藏夹已更新!",
"SELECT_CHANNEL_PLAYBACK": "请选择一个频道开始播放",
"SORT_BY": "排序方式",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "展开 ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "映射 EPG 频道",
"SUBTITLE": "为“{{channelName}}”手动选择 EPG 频道",
"SEARCH_PLACEHOLDER": "搜索 EPG 频道...",
"CURRENT_MAPPING": "当前映射",
"NO_MAPPING": "未设置 EPG 映射",
"SAVE": "保存映射",
"REMOVE": "移除映射",
"CLOSE": "关闭",
"NO_RESULTS": "未找到 EPG 频道",
"SEARCH_HINT": "输入至少 {{min}} 个字符进行搜索",
"SAVED": "EPG 映射已保存",
"REMOVED": "EPG 映射已移除",
"SAVE_FAILED": "无法更新 EPG 映射"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
+16
View File
@@ -569,6 +569,7 @@
"REMOVE_FAVORITE": "從我的最愛中移除",
"ADD_FAVORITE": "加入我的最愛",
"SHOW_DETAILS": "顯示頻道詳細資訊",
"MAP_EPG": "對應 EPG 頻道",
"FAVORITES_UPDATED": "我的最愛已更新!",
"SELECT_CHANNEL_PLAYBACK": "請選擇一個頻道以開始播放",
"SORT_BY": "排序依據",
@@ -714,6 +715,21 @@
"GROUP_EXPAND": "顯示 ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "對應 EPG 頻道",
"SUBTITLE": "為「{{channelName}}」手動選擇 EPG 頻道",
"SEARCH_PLACEHOLDER": "搜尋 EPG 頻道...",
"CURRENT_MAPPING": "目前對應",
"NO_MAPPING": "尚未設定 EPG 對應",
"SAVE": "儲存對應",
"REMOVE": "移除對應",
"CLOSE": "關閉",
"NO_RESULTS": "找不到 EPG 頻道",
"SEARCH_HINT": "輸入至少 {{min}} 個字元進行搜尋",
"SAVED": "EPG 對應已儲存",
"REMOVED": "EPG 對應已移除",
"SAVE_FAILED": "無法更新 EPG 對應"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",