From 2bd99bd524c56c6a98d5da54073100ad3446e67f Mon Sep 17 00:00:00 2001 From: Kiryl Fando Date: Mon, 31 Mar 2025 23:11:25 +0200 Subject: [PATCH 01/11] feat: update hls to the latest version --- package-lock.json | 9 +++++---- package.json | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5e0141d0..512282356 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "date-fns": "2.29.3", "dplayer": "1.27.1", "epg-parser": "0.1.6", - "hls.js": "1.4.12", + "hls.js": "1.6.0", "iptv-playlist-parser": "github:4gray/iptv-playlist-parser", "lodash": "4.17.21", "moment": "2.30.1", @@ -12527,9 +12527,10 @@ } }, "node_modules/hls.js": { - "version": "1.4.12", - "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.12.tgz", - "integrity": "sha512-1RBpx2VihibzE3WE9kGoVCtrhhDWTzydzElk/kyRbEOLnb1WIE+3ZabM/L8BqKFTCL3pUy4QzhXgD1Q6Igr1JA==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.0.tgz", + "integrity": "sha512-AlW8ymcDKZuKtzXCUmEy4nOcHRkebnShH6t6hC2+QJQP0WXlTUSSO9Kp22uSEYdCgpwkXEJsfOhqxrgO2tDctQ==", + "license": "Apache-2.0" }, "node_modules/hmac-drbg": { "version": "1.0.1", diff --git a/package.json b/package.json index 3fe6825a1..9c9e1c3ea 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "date-fns": "2.29.3", "dplayer": "1.27.1", "epg-parser": "0.1.6", - "hls.js": "1.4.12", + "hls.js": "1.6.0", "iptv-playlist-parser": "github:4gray/iptv-playlist-parser", "lodash": "4.17.21", "moment": "2.30.1", @@ -148,4 +148,4 @@ "browserslist": [ "chrome 91" ] -} \ No newline at end of file +} From ba6eaaac77b407050ae6a34505c36b68ad7fff4c Mon Sep 17 00:00:00 2001 From: Kiryl Fando Date: Wed, 2 Apr 2025 23:28:04 +0200 Subject: [PATCH 02/11] chore: return back to the classic way with languages --- README.md | 4 +- src/assets/i18n/ar.json | 4 +- src/assets/i18n/ary.json | 4 +- src/assets/i18n/by.json | 284 ++++++++++++++++++++++++++++++++++++++ src/assets/i18n/de.json | 4 +- src/assets/i18n/en.json | 4 +- src/assets/i18n/es.json | 4 +- src/assets/i18n/fr.json | 4 +- src/assets/i18n/it.json | 4 +- src/assets/i18n/ja.json | 4 +- src/assets/i18n/ko.json | 4 +- src/assets/i18n/nl.json | 3 +- src/assets/i18n/ru.json | 4 +- src/assets/i18n/tr.json | 4 +- src/assets/i18n/zh.json | 4 +- src/assets/i18n/zhtw.json | 4 +- 16 files changed, 327 insertions(+), 16 deletions(-) create mode 100644 src/assets/i18n/by.json diff --git a/README.md b/README.md index 75032eb80..e78f56738 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ IPTVnator icon

- Release + Release GitHub Workflow Status Releases Codecov Telegram Bluesky

@@ -33,7 +33,7 @@ The application is a cross-platform, open-source project built with ~~Electron~~ - Favorite channels management - Global favorites aggregated from all playlists - HTML video player with HLS.js support or Video.js-based player -- Internationalization with support for 8 languages (English, Russian, German, Korean, Spanish, Chinese, French, Italian) +- Internationalization with support for 15 languages (Arabic, Moroccan arabic, English, Russian, German, Korean, Spanish, Chinese, Traditional chinese, French, Italian, Turkish, Japanese, Dutch, Belarusian) - Custom "User Agent" header configuration for playlists - Light and Dark themes - Docker version available for self-hosting diff --git a/src/assets/i18n/ar.json b/src/assets/i18n/ar.json index 06351f826..5b737c6b7 100644 --- a/src/assets/i18n/ar.json +++ b/src/assets/i18n/ar.json @@ -220,7 +220,9 @@ "FRENCH": "الفرنسية", "ITALIAN": "الإيطالية", "TURKISH": "التركية", - "JAPANESE": "اليابانية" + "JAPANESE": "اليابانية", + "DUTCH": "الهولندية", + "BELARUSIAN": "البيلاروسية" }, "YES": "نعم", "NO": "لا", diff --git a/src/assets/i18n/ary.json b/src/assets/i18n/ary.json index 311f44381..1b68809d9 100644 --- a/src/assets/i18n/ary.json +++ b/src/assets/i18n/ary.json @@ -220,7 +220,9 @@ "FRENCH": "الفرنسية", "ITALIAN": "الإيطالية", "TURKISH": "التركية", - "JAPANESE": "اليابانية" + "JAPANESE": "اليابانية", + "DUTCH": "الهولندية", + "BELARUSIAN": "البيلاروسية" }, "YES": "آه", "NO": "لا", diff --git a/src/assets/i18n/by.json b/src/assets/i18n/by.json new file mode 100644 index 000000000..1fca3d94e --- /dev/null +++ b/src/assets/i18n/by.json @@ -0,0 +1,284 @@ +{ + "CLOSE": "Закрыць", + "PLAYLISTS": "Плэйлісты", + "HOME": { + "TITLE": "IPTVnator", + "SUBTITLE": "Выберыце плэйліст са спісу, дадайце новы з камп'ютара або загрузіце па спасылцы", + "TABS": { + "RECENTLY_ADDED": "Нядаўна дададзеныя плэйлісты", + "FILE_UPLOAD": "Загрузіць з камп'ютара", + "URL_UPLOAD": "Загрузіць па спасылцы", + "TEXT_IMPORT": "Імпартаваць з тэксту", + "STALKER_PORTAL_IMPORT": "Дадаць Stalker партал", + "XTREME_IMPORT": "Дадаць Xtreme Code" + }, + "PLAYLISTS": { + "NO_PLAYLISTS": "Пакуль яшчэ не было дададзена ніводнага плэйліста", + "ADD_FIRST": "Вы можаце дадаць плэйлісты з суседніх укладак", + "ADDED_VIA_URL": "Быў дададзены па спасылцы:", + "ADDED_VIA_FILE": "Быў загружаны з камп'ютара", + "CHANNELS": "Каналаў", + "ADDED": "Дададзены", + "SHOW_DETAILS": "Паказаць інфармацыю аб плэйлісце", + "REMOVE": "Выдаліць плэйліст", + "SEARCH_PLAYLISTS": "Пошук па назве плэйліста", + "INFO_DIALOG": { + "PLAYLIST_DETAILS": "Падрабязная інфармацыя аб плэйлісце", + "TITLE": "Назва", + "FROM_URL": "Дададзены па спасылцы", + "IMPORT_DATE": "Дата імпарту", + "CHANNELS": "Колькасць каналаў", + "CLOSE": "Закрыць", + "SAVE": "Захаваць", + "USER_AGENT": "User agent", + "ORIGINAL_FILENAME": "Імя файла пры загрузцы", + "FILE_PATH": "Шлях да файла", + "UPDATE_FAILED": "Не ўдалося абнавіць плэйліст", + "AUTO_UPDATE": "Аўтаабнаўленне", + "AUTO_UPDATE_DESCRIPTION": "Калі актываваная функцыя аўтаабнаўлення, спіс прайгравання будзе абнаўляцца аўтаматычна пры кожным запуску праграмы.", + "CUSTOM_USER_AGENT": "Некаторыя IPTV правайдэры патрабуюць указанне пэўнага карыстальніцкага агента (User Agent) для прайгравання свайго плэйліста.", + "EXPORT_PLAYLIST": "Экспартаваць плэйліст (m3u)", + "PASSWORD": "Пароль", + "SERVER_URL": "URL-адрас сервера", + "USERNAME": "Імя карыстальніка", + "MAC_ADDRESS": "MAC-адрас" + }, + "UPDATED": "Абноўлены", + "REFRESH": "Абнавіць плэйліст", + "REMOVE_DIALOG": { + "MESSAGE": "Вы ўпэўнены, што хочаце выдаліць гэты плэйліст?", + "TITLE": "Выдаліць плэйліст" + }, + "GLOBAL_FAVORITES": "Усе фаварыты", + "GLOBAL_FAVORITES_DESCRIPTION": "Аўтаматычна згенераваны плэйліст, які ўключае ў сябе фаварыты з усіх плэйлістоў", + "MY_PLAYLISTS": "Мае плэйлісты", + "MY_PLAYLISTS_SUBTITLE": "Усе наяўныя плэйлісты", + "PLAYLIST_UPDATE_SUCCESS": "Плэйліст быў паспяхова абноўлены!", + "STALKER_PORTAL": "Stalker партал", + "XTREAM_PLAYLIST": "Xtream плэйліст" + }, + "FILE_UPLOAD": { + "DRAG_DROP": "Перацягніце файл у гэтую вобласць", + "OR": "або", + "CHOOSE_PLAYLIST": "выберыце плэйліст", + "REJECTED": "На жаль, гэты фармат файлаў не падтрымліваецца {{filename}}." + }, + "URL_UPLOAD": { + "PLAYLIST_URL": "Спасылка на плэйліст (*.m3u або *.m3u8)", + "ADD_PLAYLIST": "Дадаць плэйліст" + }, + "TEXT_IMPORT": { + "LABEL": "Устаўце плэйліст фармату m3u(8) у гэта поле", + "BUTTON_LABEL": "Імпартаваць" + }, + "XTREAM_PLAYLIST": { + "TITLE": "Назва плэйліста", + "SERVER_URL": "Сервер URL", + "USERNAME": "Карыстальнік", + "PASSWORD": "Пароль", + "ADD": "Дадаць", + "TEST_CREDENTIALS": "Праверыць", + "URL_VALIDATION_ERROR": "Павінен быць сапраўдны URL-адрас з пратаколам (напрыклад, http://example.com або https://example.com:4324)." + }, + "STALKER_PORTAL": { + "ADD": "Дадаць", + "TITLE": "Назва", + "MAC_ADDRESS": "MAC-адрас", + "SERVER_URL": "URL сервера", + "URL_VALIDATION_ERROR": "Павінен быць сапраўдны URL-адрас з пратаколам (напрыклад, http://example.com/c або https://example.com/stalker_portal/c)." + }, + "FILTER_BY_TYPE": "Фільтраваць па тыпу", + "IMPORTED_AS_TEXT": "Імпартавана як тэкст", + "FILTER_BY_NAME": "Фільтраваць па імені", + "PARSING_ERROR": "Памылка парсінгу, несапраўдны плэйліст:" + }, + "LANGUAGES": { + "ARABIC": "العربية", + "MOROCCAN_ARABIC": "العربية (اللهجة المغربية)", + "ENGLISH": "English", + "KOREAN": "한국어", + "RUSSIAN": "Русский", + "GERMAN": "Deutsch", + "SPANISH": "Español", + "CHINESE": "简体中文", + "TRADITIONAL_CHINESE": "繁體中文", + "FRENCH": "Français", + "ITALIAN": "Italiano", + "TURKISH": "Türkçe", + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" + }, + "SETTINGS": { + "TITLE": "Налады / IPTVnator", + "SUBTITLE": "Тут можна змяніць агульныя налады праграмы", + "DESCRIPTION": "Скончыўшы наладу, не забудзьцеся пацвердзіць новыя налады кнопкай 'Захаваць'", + "EPG_URL_LABEL": "Спасылка на праграму каналаў (EPG) (*.xml або *.xml.gz)", + "EPG_URL_PLACEHOLDER": "Увядзіце спасылку", + "REFRESH_EPG": "Абнавіць праграму каналаў (EPG)", + "VIDEO_PLAYER_LABEL": "Відэапрайгравальнік", + "VIDEO_PLAYER_PLACEHOLDER": "Выберыце са спісу", + "VERSION": "Версія праграмы", + "SAVE_CHANGES": "Захаваць", + "BACK_TO_HOME": "Назад", + "NEW_VERSION_AVAILABLE": "Даступная новая версія праграмы", + "LATEST_VERSION": "Вы выкарыстоўваеце апошнюю версію праграмы", + "LANGUAGE": "Мова", + "SETTINGS_SAVED": "Новыя налады былі паспяхова захаваны!", + "THEME": "Тэма афармлення", + "SHOW_CAPTIONS": "Адлюстроўваць субтытры", + "ADD_EPG_SOURCE": "Дадаць крыніцу EPG", + "EPG_URL_ERROR": "Уведзенае значэнне не з'яўляецца URL-адрасам.", + "VIDEO_PLAYER_DESCRIPTION": "Выбраць стандартны відэапрайгравальнік", + "LANGUAGE_DESCRIPTION": "Выбраць мову праграмы", + "THEME_DESCRIPTION": "Выбраць візуальную тэму афармлення", + "SHOW_CAPTIONS_DESCRIPTION": "Паказаць або схаваць субтытры па змаўчанні.", + "VERSION_DESCRIPTION": "Бягучая версія праграмы", + "EPG_NOTE": "На гэты момант EPG даступны толькі ў натыўнай версіі IPTVnator.", + "EPG_NOTE_URL_TEXT": "Падрабязней тут", + "IMPORT_EXPORT_DATA": "Імпарт/экспарт плэйлістоў", + "IMPORT_EXPORT_DATA_DESCRIPTION": "Экспарт або імпарт плэйлістоў у фармаце JSON, які выкарыстоўваецца ў праграме.", + "IMPORT_DATA": "Імпарт", + "EXPORT_DATA": "Экспарт", + "REMOVE_ALL": "Выдаліць плэйліст", + "REMOVE_ALL_BUTTON": "Выдаліць", + "REMOVE_ALL_DESCRIPTION": "Гэта дзеянне выдаліць усе існуючыя плэйлісты з праграмы.", + "REMOVE_DIALOG": { + "TITLE": "Выдаліць усе плэйлісты", + "MESSAGE": "Вы ўпэўнены, што хочаце выдаліць усе плэйлісты з праграмы?" + }, + "IMPORT_ERROR": "Памылка імпарту, калі ласка, паспрабуйце імпартаваць іншы файл.", + "PLAYLISTS_REMOVED": "Усе плэйлісты былі выдалены.", + "VLC_PLAYER_PATH_LABEL": "Шлях да VLC прайгравальніка", + "VLC_PLAYER_PATH": "Шлях да VLC прайгравальніка", + "MPV_PLAYER_PATH_LABEL": "Шлях да mpv прайгравальніка", + "MPV_PLAYER_PATH": "Шлях да mpv прайгравальніка", + "VLC_PLAYER_PATH_DESCRIPTION": "Усталюйце шлях да прайгравальніка VLC у вашай сістэме. \nЁн будзе выкарыстоўваць прадастаўлены шлях да бінарнага файла VLC замест шляху па змаўчанні." + }, + "THEMES": { + "DARK_THEME": "Цёмная тэма", + "LIGHT_THEME": "Светлая тэма" + }, + "CHANNELS": { + "SEARCH_CHANNEL": "Пошук каналаў", + "UPLOAD_OR_SELECT_OTHER_PLAYLIST": "Загрузіць або выбраць іншы плэйліст", + "ALL_CHANNELS": "Усе каналы", + "GROUPS": "Групы", + "UNGROUPED": "Незагрупаваныя", + "UNNAMED_CHANNEL": "Канал без назвы", + "FAVORITES": "Выбраныя", + "NO_FAVORITES": "Выбраных каналаў пакуль няма", + "USE_STAR_TO_FAVORITE": "Выкарыстоўвайце значок зоркі, каб дадаваць каналы ў выбранае", + "REMOVE_FAVORITE": "Выдаліць са спісу фаварытаў", + "FAVORITES_UPDATED": "Спіс фаварытаў быў абноўлены!" + }, + "TOP_MENU": { + "OPEN_CHANNELS_LIST": "Адкрыць спіс каналаў", + "TOGGLE_FAVORITE_FLAG": "Выбраны", + "OPEN_EPG_LIST": "Адкрыць праграму (EPG)", + "OPEN_MULTI_EPG": "Адкрыць мульты-EPG прагляд" + }, + "EPG": { + "NEXT_DAY": "Наступны дзень", + "PREVIOUS_DAY": "Папярэдні дзень", + "LIVE_NOW": "Цяпер", + "LIVE_STREAM": "Прамая трансляцыя", + "TIMESHIFT_AVAILABLE": "Даступная функцыя архіва (timeshift). Націсніце на перадачу для прайгравання.", + "EPG_NOT_AVAILABLE_DATE": "Ой, праграма на гэты дзень, на жаль, адсутнічае.", + "EPG_NOT_AVAILABLE_CHANNEL_TITLE": "Праграма для гэтага канала недаступная.", + "EPG_NOT_AVAILABLE_CHANNEL_DESCRIPTION": "Паспрабуйце змяніць або абнавіць спасылку на EPG у наладах праграмы.", + "FETCH_EPG": "Загружаю праграму ТБ-перадач (EPG)...", + "ERROR": "Ой, не ўдалося загрузіць праграму каналаў (EPG)", + "DOWNLOAD_SUCCESS": "Праграма каналаў (EPG) была паспяхова загружана.", + "PROGRAM_DIALOG": { + "PROGRAM_DETAILS": "Падрабязнасці перадачы", + "TITLE": "Назва", + "CATEGORY": "Катэгорыя", + "PARENTAL_RATING_SYSTEM": "Возраснае абмежаванне", + "DESCRIPTION": "Апісанне", + "LANGUAGE": "Мова", + "SHOW_PROGRAM_DETAILS": "Паказаць падрабязнасці" + } + }, + "NO": "Не", + "YES": "Так", + "MENU": { + "OPEN": "Адкрыць меню", + "SUPPORT_ARIA": "Падтрымаць IPTVnator на GitHub", + "SETTINGS": "Налады", + "SETTINGS_ARIA": "Адкрыць налады", + "BUG_REPORT": "Паведаміць аб памылцы", + "WHAT_IS_NEW": "Што новага?", + "ABOUT": "Аб праграме", + "ABOUT_ARIA": "Аб праграме", + "SUPPORT_PROJECT": "Падтрымаць праект" + }, + "ABOUT": { + "TITLE": "Аб праграме", + "DESCRIPTION": "Кросплатформавая праграма для прайгравання IPTV з мноствам функцый, такіх як падтрымка плэйлістоў m3u і m3u8, фаварыты, ТБ-гід, ТБ-архіў/даганянне і іншае.", + "VERSION": "Версія", + "GITHUB_TOOLTIP": "Рэпазітар праграмы на GitHub", + "BUY_ME_A_COFFEE_TOOLTIP": "Падтрымаць распрацоўшчыка", + "TWITTER_TOOLTIP": "Падзяліцца ў Twitter" + }, + "UPDATE_AVAILABLE": "Даступна абнаўленне", + "REFRESH": "Абнавіць", + "XTREAM": { + "RATING": "Рэйтынг", + "RELEASE_DATE": "Дата выпуску", + "ACTORS": "Акцёры", + "PLAY": "Прайграць", + "GENRE": "Жанр", + "DURATION": "Працягласць", + "COUNTRY": "Краіна", + "NAME": "Назва", + "DIRECTOR": "Рэжысёр", + "CAST": "Акцёрскі склад", + "EPISODE_RUN_TIME": "Працягласць эпізоду", + "AGE": "Узрост", + "EPISODE": "Эпізод", + "YEAR": "Год", + "YOUTUBE_TRAILER": "Трэйлер на YouTube", + "DESCRIPTION": "Апісанне", + "KINOPOISK_RATING": "Рэйтынг на Кінапоіск", + "IMDB_RATING": "Рэйтынг на IMDB" + }, + "PORTALS": { + "ALL_CATEGORIES": "Усе катэгорыі", + "ADD_TO_FAVORITES": "Дадаць у выбранае", + "REMOVE_FROM_FAVORITES": "Выдаліць з выбранага", + "MY_FAVORITES": "Выбранае", + "COPY_STREAM_URL": "Капіраваць URL-адрас патоку", + "ERROR_VIEW": { + "DELETE": "Выдаліць", + "ACCOUNT_EXPIRED": { + "TITLE": "Тэрмін дзеяння ўліковага запісу скончыўся", + "DESCRIPTION": "Тэрмін дзеяння гэтага ўліковага запісу скончыўся. \nКалі ласка, праверце ўліковыя дадзеныя ў наладах плэйліста або выдаліце яго." + }, + "HOME": "На галоўную", + "EMPTY_CATEGORY": { + "TITLE": "Пустая катэгорыя", + "DESCRIPTION": "У гэтай катэгорыі няма кантэнту. Выберыце іншую катэгорыю або зменіце тып кантэнту." + }, + "UNAUTHORIZED": { + "TITLE": "Несанкцыянаваны", + "DESCRIPTION": "Калі ласка, праверце ўліковыя дадзеныя ў наладах плэйліста або выдаліце іх." + }, + "NOT_FOUND": { + "TITLE": "Партал не знойдзены" + }, + "UNKNOWN_ERROR": { + "TITLE": "Нешта пайшло не так", + "DESCRIPTION": "Невядомая памылка. Паўтарыце спробу пазней." + }, + "PLAYLIST_SETTINGS": "Налады плэйліста" + }, + "STREAM_URL_COPIED": "URL-адрас патоку быў скапіяваны ў буфер абмену.", + "EMPTY_LIST_VIEW": { + "NO_SEARCH_RESULTS": "Нічога не знойдзена, паспрабуйце змяніць пошукавы запыт" + }, + "REMOVED_FROM_FAVORITES": "Выдалена з выбранага", + "ADDED_TO_FAVORITES": "Дададзена ў выбранае" + }, + "INFORMATION": "Інфармацыя" +} diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index f3f95849c..180d55876 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -140,7 +140,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "SETTINGS": { "BACK_TO_HOME": "Zurück", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 6b40d5848..4722c6f8b 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -220,7 +220,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "Yes", "NO": "No", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 83ee6253e..b6f92625e 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -183,7 +183,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "Sí", "NO": "No", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index ae5a132d6..ae0ff60a9 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -182,7 +182,9 @@ "TRADITIONAL_CHINESE": "繁體中文", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "Oui", "NO": "Non", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 7beaa812f..e4a17ef18 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -216,7 +216,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "Sì", "NO": "No", diff --git a/src/assets/i18n/ja.json b/src/assets/i18n/ja.json index 831d28713..f798dcd4f 100644 --- a/src/assets/i18n/ja.json +++ b/src/assets/i18n/ja.json @@ -208,7 +208,9 @@ "FRENCH": "フランス語", "ITALIAN": "イタリア語", "TURKISH": "トルコ語", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "はい", "NO": "いいえ", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index 96607ef7c..58e898eaa 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -172,7 +172,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "Yes", "NO": "No", diff --git a/src/assets/i18n/nl.json b/src/assets/i18n/nl.json index 427f99517..430b2b774 100644 --- a/src/assets/i18n/nl.json +++ b/src/assets/i18n/nl.json @@ -220,7 +220,8 @@ "ITALIAN": "Italiano", "TURKISH": "Türkçe", "JAPANESE": "日本語", - "DUTCH": "Nederlands" + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "Ja", "NO": "Nee", diff --git a/src/assets/i18n/ru.json b/src/assets/i18n/ru.json index 8c7ae46c8..9fe8c4d99 100644 --- a/src/assets/i18n/ru.json +++ b/src/assets/i18n/ru.json @@ -196,7 +196,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "NO": "Нет", "YES": "Да", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index 52d99fa3c..9dccfcff4 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -208,7 +208,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "Evet", "NO": "Hayır", diff --git a/src/assets/i18n/zh.json b/src/assets/i18n/zh.json index 23bf3b996..166dc3d7a 100644 --- a/src/assets/i18n/zh.json +++ b/src/assets/i18n/zh.json @@ -172,7 +172,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "是", "NO": "否", diff --git a/src/assets/i18n/zhtw.json b/src/assets/i18n/zhtw.json index 684294766..43512b7c4 100644 --- a/src/assets/i18n/zhtw.json +++ b/src/assets/i18n/zhtw.json @@ -175,7 +175,9 @@ "FRENCH": "Français", "ITALIAN": "Italiano", "TURKISH": "Türkçe", - "JAPANESE": "日本語" + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская" }, "YES": "是", "NO": "否", From b7382b2fc88ee4179408979540d7cf66e4341dcb Mon Sep 17 00:00:00 2001 From: Kiryl Fando Date: Wed, 2 Apr 2025 23:31:47 +0200 Subject: [PATCH 03/11] chore: add by language to enum --- src/app/settings/language.enum.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/settings/language.enum.ts b/src/app/settings/language.enum.ts index 23c1fee8f..1e6734d8a 100644 --- a/src/app/settings/language.enum.ts +++ b/src/app/settings/language.enum.ts @@ -16,4 +16,5 @@ export enum Language { TURKISH = 'tr', JAPANESE = 'ja', DUTCH = 'nl', + BELARUSIAN = 'by', } From 7eaa91d2b837abfade426d4d064563a30dd98519 Mon Sep 17 00:00:00 2001 From: Kiryl Fando Date: Wed, 2 Apr 2025 23:43:01 +0200 Subject: [PATCH 04/11] chore: japan list of langs --- src/assets/i18n/ja.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/ja.json b/src/assets/i18n/ja.json index f798dcd4f..333f8b54d 100644 --- a/src/assets/i18n/ja.json +++ b/src/assets/i18n/ja.json @@ -209,8 +209,8 @@ "ITALIAN": "イタリア語", "TURKISH": "トルコ語", "JAPANESE": "日本語", - "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "DUTCH": "オランダ語", + "BELARUSIAN": "ベラルーシ語" }, "YES": "はい", "NO": "いいえ", From 206925ca19f083a36d7d7e913df4a2c21a58cfa4 Mon Sep 17 00:00:00 2001 From: Kiryl Fando Date: Mon, 31 Mar 2025 23:11:25 +0200 Subject: [PATCH 05/11] feat: update hls to the latest version --- package-lock.json | 9 +++++---- package.json | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5e0141d0..512282356 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "date-fns": "2.29.3", "dplayer": "1.27.1", "epg-parser": "0.1.6", - "hls.js": "1.4.12", + "hls.js": "1.6.0", "iptv-playlist-parser": "github:4gray/iptv-playlist-parser", "lodash": "4.17.21", "moment": "2.30.1", @@ -12527,9 +12527,10 @@ } }, "node_modules/hls.js": { - "version": "1.4.12", - "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.12.tgz", - "integrity": "sha512-1RBpx2VihibzE3WE9kGoVCtrhhDWTzydzElk/kyRbEOLnb1WIE+3ZabM/L8BqKFTCL3pUy4QzhXgD1Q6Igr1JA==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.0.tgz", + "integrity": "sha512-AlW8ymcDKZuKtzXCUmEy4nOcHRkebnShH6t6hC2+QJQP0WXlTUSSO9Kp22uSEYdCgpwkXEJsfOhqxrgO2tDctQ==", + "license": "Apache-2.0" }, "node_modules/hmac-drbg": { "version": "1.0.1", diff --git a/package.json b/package.json index 3fe6825a1..9c9e1c3ea 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "date-fns": "2.29.3", "dplayer": "1.27.1", "epg-parser": "0.1.6", - "hls.js": "1.4.12", + "hls.js": "1.6.0", "iptv-playlist-parser": "github:4gray/iptv-playlist-parser", "lodash": "4.17.21", "moment": "2.30.1", @@ -148,4 +148,4 @@ "browserslist": [ "chrome 91" ] -} \ No newline at end of file +} From 07a21dde4567a3b678e127b43ca883e5340205af Mon Sep 17 00:00:00 2001 From: Kiryl Fando Date: Fri, 4 Apr 2025 14:56:27 +0200 Subject: [PATCH 06/11] feat: add polish language --- README.md | 18 +- src/app/settings/language.enum.ts | 1 + src/assets/i18n/ar.json | 3 +- src/assets/i18n/ary.json | 3 +- src/assets/i18n/de.json | 3 +- src/assets/i18n/en.json | 3 +- src/assets/i18n/es.json | 3 +- src/assets/i18n/fr.json | 3 +- src/assets/i18n/it.json | 3 +- src/assets/i18n/ja.json | 3 +- src/assets/i18n/ko.json | 3 +- src/assets/i18n/nl.json | 3 +- src/assets/i18n/pl.json | 317 ++++++++++++++++++++++++++++++ src/assets/i18n/ru.json | 3 +- src/assets/i18n/tr.json | 3 +- src/assets/i18n/zh.json | 3 +- src/assets/i18n/zhtw.json | 3 +- 17 files changed, 363 insertions(+), 15 deletions(-) create mode 100644 src/assets/i18n/pl.json diff --git a/README.md b/README.md index e78f56738..3baad53ad 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,23 @@ The application is a cross-platform, open-source project built with ~~Electron~~ - Favorite channels management - Global favorites aggregated from all playlists - HTML video player with HLS.js support or Video.js-based player -- Internationalization with support for 15 languages (Arabic, Moroccan arabic, English, Russian, German, Korean, Spanish, Chinese, Traditional chinese, French, Italian, Turkish, Japanese, Dutch, Belarusian) +- Internationalization with support for 16 languages: + * Arabic + * Moroccan arabic + * English + * Russian + * German + * Korean + * Spanish + * Chinese + * Traditional chinese + * French + * Italian + * Turkish + * Japanese + * Dutch + * Belarusian + * Polish - Custom "User Agent" header configuration for playlists - Light and Dark themes - Docker version available for self-hosting diff --git a/src/app/settings/language.enum.ts b/src/app/settings/language.enum.ts index 1e6734d8a..0af6e0246 100644 --- a/src/app/settings/language.enum.ts +++ b/src/app/settings/language.enum.ts @@ -17,4 +17,5 @@ export enum Language { JAPANESE = 'ja', DUTCH = 'nl', BELARUSIAN = 'by', + POLISH = 'pl', } diff --git a/src/assets/i18n/ar.json b/src/assets/i18n/ar.json index 5b737c6b7..05414ff6a 100644 --- a/src/assets/i18n/ar.json +++ b/src/assets/i18n/ar.json @@ -222,7 +222,8 @@ "TURKISH": "التركية", "JAPANESE": "اليابانية", "DUTCH": "الهولندية", - "BELARUSIAN": "البيلاروسية" + "BELARUSIAN": "البيلاروسية", + "POLISH": "البولندية" }, "YES": "نعم", "NO": "لا", diff --git a/src/assets/i18n/ary.json b/src/assets/i18n/ary.json index 1b68809d9..c1b3f6889 100644 --- a/src/assets/i18n/ary.json +++ b/src/assets/i18n/ary.json @@ -222,7 +222,8 @@ "TURKISH": "التركية", "JAPANESE": "اليابانية", "DUTCH": "الهولندية", - "BELARUSIAN": "البيلاروسية" + "BELARUSIAN": "البيلاروسية", + "POLISH": "البولندية" }, "YES": "آه", "NO": "لا", diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 180d55876..f40c144cc 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -142,7 +142,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "SETTINGS": { "BACK_TO_HOME": "Zurück", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 4722c6f8b..f5a8f1bcf 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -222,7 +222,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "Yes", "NO": "No", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index b6f92625e..108a05169 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -185,7 +185,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "Sí", "NO": "No", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index ae0ff60a9..1c81628ad 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -184,7 +184,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "Oui", "NO": "Non", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index e4a17ef18..92c847e42 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -218,7 +218,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "Sì", "NO": "No", diff --git a/src/assets/i18n/ja.json b/src/assets/i18n/ja.json index 333f8b54d..63673cc58 100644 --- a/src/assets/i18n/ja.json +++ b/src/assets/i18n/ja.json @@ -210,7 +210,8 @@ "TURKISH": "トルコ語", "JAPANESE": "日本語", "DUTCH": "オランダ語", - "BELARUSIAN": "ベラルーシ語" + "BELARUSIAN": "ベラルーシ語", + "POLISH": "ポーランド語" }, "YES": "はい", "NO": "いいえ", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index 58e898eaa..0763ca939 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -174,7 +174,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "Yes", "NO": "No", diff --git a/src/assets/i18n/nl.json b/src/assets/i18n/nl.json index 430b2b774..e16eabf51 100644 --- a/src/assets/i18n/nl.json +++ b/src/assets/i18n/nl.json @@ -221,7 +221,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "Ja", "NO": "Nee", diff --git a/src/assets/i18n/pl.json b/src/assets/i18n/pl.json new file mode 100644 index 000000000..3344992e9 --- /dev/null +++ b/src/assets/i18n/pl.json @@ -0,0 +1,317 @@ +{ + "CLOSE": "Zamknij", + "PLAYLISTS": "Listy odtwarzania", + "HOME": { + "TITLE": "IPTVnator", + "SUBTITLE": "Wybierz listę odtwarzania z listy lub dodaj nową listę odtwarzania", + "TABS": { + "RECENTLY_ADDED": "Ostatnio dodane listy odtwarzania", + "FILE_UPLOAD": "Dodaj przez przesłanie pliku", + "URL_UPLOAD": "Dodaj przez URL", + "TEXT_IMPORT": "Importuj z tekstu", + "XTREME_IMPORT": "Dodaj kod Xtreme", + "STALKER_PORTAL_IMPORT": "Dodaj portal Stalker" + }, + "PLAYLISTS": { + "NO_PLAYLISTS": "Nie dodano żadnych list odtwarzania", + "ADD_FIRST": "Dodaj swoją pierwszą listę odtwarzania", + "ADDED_VIA_URL": "Dodano przez przesłanie URL. URL:", + "ADDED_VIA_FILE": "Dodano przez przesłanie pliku", + "XTREAM_PLAYLIST": "Lista odtwarzania Xtream", + "STALKER_PORTAL": "Portal Stalker", + "CHANNELS": "Kanały", + "ADDED": "Dodano", + "SHOW_DETAILS": "Pokaż szczegóły listy odtwarzania", + "REMOVE": "Usuń listę odtwarzania", + "SEARCH_PLAYLISTS": "Szukaj list odtwarzania według tytułu", + "INFO_DIALOG": { + "PLAYLIST_DETAILS": "Szczegóły listy odtwarzania", + "TITLE": "Tytuł", + "FROM_URL": "Dodano z URL", + "IMPORT_DATE": "Data importu", + "CHANNELS": "Liczba kanałów", + "CLOSE": "Zamknij", + "SAVE": "Zapisz", + "USER_AGENT": "Agent użytkownika", + "ORIGINAL_FILENAME": "Oryginalna nazwa pliku", + "FILE_PATH": "Ścieżka pliku", + "UPDATE_FAILED": "Ostatnia aktualizacja listy odtwarzania nie powiodła się", + "AUTO_UPDATE": "Automatyczna aktualizacja", + "AUTO_UPDATE_DESCRIPTION": "Jeśli funkcja automatycznego odświeżania jest aktywna, lista odtwarzania będzie automatycznie aktualizowana przy każdym uruchomieniu aplikacji.", + "CUSTOM_USER_AGENT": "Niektórzy dostawcy IPTV wymagają określonego agenta użytkownika, aby odtworzyć ich listę odtwarzania.", + "EXPORT_PLAYLIST": "Eksportuj listę odtwarzania jako m3u", + "SERVER_URL": "URL serwera", + "USERNAME": "Nazwa użytkownika", + "PASSWORD": "Hasło", + "MAC_ADDRESS": "Adres Mac", + "PLAYLIST_EXPORT_SUCCESS": "Lista odtwarzania została pomyślnie wyeksportowana.", + "PLAYLIST_EXPORT_ERROR": "Błąd: Eksport listy odtwarzania nie powiódł się." + }, + "REMOVE_DIALOG": { + "TITLE": "Usuń listę odtwarzania", + "MESSAGE": "Czy na pewno chcesz całkowicie usunąć tę listę odtwarzania?", + "SUCCESS": "Lista odtwarzania została pomyślnie usunięta" + }, + "UPDATED": "Zaktualizowano", + "REFRESH": "Odśwież listę odtwarzania", + "GLOBAL_FAVORITES": "Globalne ulubione", + "GLOBAL_FAVORITES_DESCRIPTION": "Automatycznie wygenerowana lista odtwarzania z zagregowanymi ulubionymi ze wszystkich list odtwarzania", + "MY_PLAYLISTS": "Moje listy odtwarzania", + "MY_PLAYLISTS_SUBTITLE": "wszystkie dostępne listy odtwarzania", + "PLAYLIST_UPDATE_SUCCESS": "Sukces! Lista odtwarzania została pomyślnie zaktualizowana.", + "PLAYLIST_UPDATE_ERROR": "Błąd aktualizacji szczegółów listy odtwarzania." + }, + "FILE_UPLOAD": { + "DRAG_DROP": "Przeciągnij i upuść pliki tutaj", + "OR": "lub", + "CHOOSE_PLAYLIST": "wybierz listę odtwarzania", + "REJECTED": "Plik został odrzucony, nieobsługiwany format pliku {{filename}}." + }, + "URL_UPLOAD": { + "PLAYLIST_URL": "URL listy odtwarzania (m3u, m3u8)", + "ADD_PLAYLIST": "Dodaj listę odtwarzania", + "CORS_NOTE": "Uwaga: Aby uniknąć problemów z CORS, aplikacja używa publicznej usługi proxy CORS. Jeśli chcesz przesłać listę odtwarzania z wrażliwymi danymi, bezpieczniej jest zaimportować ją z pliku." + }, + "TEXT_IMPORT": { + "LABEL": "Wklej listę odtwarzania m3u(8) jako tekst", + "BUTTON_LABEL": "Importuj" + }, + "XTREAM_PLAYLIST": { + "TITLE": "Tytuł listy odtwarzania", + "SERVER_URL": "URL serwera", + "USERNAME": "Nazwa użytkownika", + "PASSWORD": "Hasło", + "ADD": "Dodaj", + "TEST_CREDENTIALS": "Testuj dane uwierzytelniające", + "URL_VALIDATION_ERROR": "Powinien to być poprawny URL z protokołem (np. http://example.com lub https://example.com:4324)" + }, + "STALKER_PORTAL": { + "TITLE": "Tytuł", + "MAC_ADDRESS": "Adres Mac", + "SERVER_URL": "URL serwera", + "URL_VALIDATION_ERROR": "Powinien to być poprawny URL z protokołem (np. http://example.com/c lub https://example.com/stalker_portal/c)", + "ADD": "Dodaj" + }, + "FILTER_BY_NAME": "Filtruj według nazwy", + "FILTER_BY_TYPE": "Filtruj według typu", + "SORT_PLAYLISTS": "Sortuj listy odtwarzania", + "SORT_BY": "Sortuj według", + "SORT_OPTIONS": { + "NAME_ASC": "Nazwa (A-Z)", + "NAME_DESC": "Nazwa (Z-A)", + "NEWEST": "Data dodania (najnowsze pierwsze)", + "OLDEST": "Data dodania (najstarsze pierwsze)" + }, + "IMPORTED_AS_TEXT": "Zaimportowano jako tekst", + "PARSING_ERROR": "Błąd: Analiza nie powiodła się, nieprawidłowa lista odtwarzania:" + }, + "SETTINGS": { + "TITLE": "Ustawienia / IPTVnator", + "SUBTITLE": "Zmień konfigurację aplikacji", + "DESCRIPTION": "Dostosuj opcje z poniższej listy i potwierdź przyciskiem „Zapisz zmiany”", + "EPG_URL_LABEL": "URL EPG (*.xml lub *.xml.gz)", + "EPG_URL_PLACEHOLDER": "Wprowadź URL", + "REFRESH_EPG": "Odśwież EPG", + "VIDEO_PLAYER_LABEL": "Odtwarzacz wideo", + "VIDEO_PLAYER_PLACEHOLDER": "Wybierz opcję", + "VERSION": "Wersja", + "SAVE_CHANGES": "Zapisz zmiany", + "BACK_TO_HOME": "Wróć", + "NEW_VERSION_AVAILABLE": "Dostępna jest nowa wersja", + "LATEST_VERSION": "Używasz najnowszej wersji", + "LANGUAGE": "Język", + "SETTINGS_SAVED": "Sukces! Konfiguracja została zapisana.", + "THEME": "Motyw wizualny", + "SHOW_CAPTIONS": "Pokaż napisy", + "ADD_EPG_SOURCE": "Dodaj źródło EPG", + "EPG_URL_ERROR": "Wartość nie jest prawidłowym URL", + "VIDEO_PLAYER_DESCRIPTION": "Wybierz domyślny odtwarzacz wideo", + "LANGUAGE_DESCRIPTION": "Wybierz język aplikacji", + "THEME_DESCRIPTION": "Wybierz motyw wizualny aplikacji", + "SHOW_CAPTIONS_DESCRIPTION": "Domyślnie pokaż lub ukryj napisy", + "VERSION_DESCRIPTION": "Aktualna wersja aplikacji", + "EPG_NOTE": "Obecnie EPG jest dostępne tylko w wersji IPTVnator opartej na Electron.", + "EPG_NOTE_URL_TEXT": "Sprawdź tutaj", + "IMPORT_EXPORT_DATA": "Import/eksport list odtwarzania", + "IMPORT_EXPORT_DATA_DESCRIPTION": "Eksportuj lub importuj listy odtwarzania w formacie JSON używanym w aplikacji.", + "IMPORT_DATA": "Importuj", + "EXPORT_DATA": "Eksportuj", + "REMOVE_ALL": "Usuń listy odtwarzania", + "REMOVE_ALL_BUTTON": "Usuń", + "REMOVE_ALL_DESCRIPTION": "Spowoduje to usunięcie wszystkich istniejących list odtwarzania z aplikacji.", + "REMOVE_DIALOG": { + "TITLE": "Usuń wszystkie listy odtwarzania", + "MESSAGE": "Czy na pewno chcesz usunąć wszystkie listy odtwarzania z aplikacji?" + }, + "IMPORT_ERROR": "Błąd importu, spróbuj z innym plikiem.", + "PLAYLISTS_REMOVED": "Wszystkie listy odtwarzania zostały usunięte.", + "MPV_PLAYER_PATH_LABEL": "Ścieżka mpv", + "MPV_PLAYER_PATH_DESCRIPTION": "Ustaw ścieżkę do odtwarzacza mpv w systemie. Będzie używać podanej ścieżki do pliku binarnego mpv zamiast tego znalezionego w $PATH.", + "MPV_PLAYER_PATH": "Ścieżka odtwarzacza mpv", + "VLC_PLAYER_PATH_LABEL": "Ścieżka VLC", + "VLC_PLAYER_PATH_DESCRIPTION": "Ustaw ścieżkę do odtwarzacza VLC w systemie. Będzie używać podanej ścieżki do pliku binarnego VLC zamiast domyślnej ścieżki dla naszego systemu.", + "VLC_PLAYER_PATH": "Ścieżka odtwarzacza VLC", + "REMOTE_CONTROL": "Zdalne sterowanie", + "REMOTE_CONTROL_DESCRIPTION": "Włącz zdalne sterowanie aplikacją.", + "REMOTE_CONTROL_PORT": "Port zdalnego sterowania", + "REMOTE_CONTROL_PORT_DESCRIPTION": "Port używany do zdalnego sterowania aplikacją. Domyślnie używany jest port 3000." + }, + "THEMES": { + "DARK_THEME": "Ciemny motyw", + "LIGHT_THEME": "Jasny motyw" + }, + "CHANNELS": { + "SEARCH_CHANNEL": "Szukaj kanału", + "UPLOAD_OR_SELECT_OTHER_PLAYLIST": "Prześlij lub wybierz inną listę odtwarzania", + "ALL_CHANNELS": "Wszystkie kanały", + "GROUPS": "Grupy", + "UNGROUPED": "Niegrupowane", + "UNNAMED_CHANNEL": "Nienazwany kanał", + "FAVORITES": "Ulubione", + "NO_FAVORITES": "Brak ulubionych", + "USE_STAR_TO_FAVORITE": "Użyj ikony „gwiazdki”, aby dodać kanały do ulubionych.", + "REMOVE_FAVORITE": "Usuń z ulubionych", + "FAVORITES_UPDATED": "Ulubione zostały zaktualizowane!", + "SORT_BY": "Sortuj według", + "SORT_BY_DATE": "Sortuj według daty dodania (najnowsze pierwsze)", + "SORT_BY_RATING": "Sortuj według oceny", + "SORT_BY_NAME": "Sortuj według nazwy (A-Z)" + }, + "TOP_MENU": { + "OPEN_CHANNELS_LIST": "Otwórz listę kanałów", + "TOGGLE_FAVORITE_FLAG": "Przełącz flagę ulubionych", + "OPEN_EPG_LIST": "Otwórz listę EPG", + "OPEN_MULTI_EPG": "Otwórz widok Multi-EPG" + }, + "EPG": { + "TITLE": "Elektroniczny przewodnik po programach", + "NEXT_DAY": "Następny dzień", + "PREVIOUS_DAY": "Poprzedni dzień", + "LIVE_NOW": "Na żywo teraz", + "LIVE_STREAM": "Transmisja na żywo", + "TIMESHIFT_AVAILABLE": "Dostępne jest przesunięcie czasowe, kliknij, aby odtworzyć", + "EPG_NOT_AVAILABLE_DATE": "Ups, EPG nie jest dostępne dla wybranej daty", + "EPG_NOT_AVAILABLE_CHANNEL_TITLE": "Ups, EPG nie jest dostępne dla tego kanału.", + "EPG_NOT_AVAILABLE_CHANNEL_DESCRIPTION": "Dodaj/zmień URL listy EPG w ustawieniach aplikacji.", + "FETCH_EPG": "Pobieranie danych EPG...", + "ERROR": "Ups, nie można załadować EPG.", + "DOWNLOAD_SUCCESS": "EPG zostało pomyślnie pobrane.", + "PROGRAM_DIALOG": { + "PROGRAM_DETAILS": "Szczegóły programu telewizyjnego", + "TITLE": "Tytuł", + "CATEGORY": "Kategoria", + "PARENTAL_RATING_SYSTEM": "System oceny treści telewizyjnych", + "DESCRIPTION": "Opis", + "LANGUAGE": "Język", + "SHOW_PROGRAM_DETAILS": "Pokaż szczegóły programu" + }, + "FETCH_SUCCESS": "EPG zostało pomyślnie pobrane" + }, + "LANGUAGES": { + "ARABIC": "العربية", + "MOROCCAN_ARABIC": "العربية (اللهجة المغربية)", + "ENGLISH": "English", + "KOREAN": "한국어", + "RUSSIAN": "Русский", + "GERMAN": "Deutsch", + "SPANISH": "Español", + "CHINESE": "简体中文", + "TRADITIONAL_CHINESE": "繁體中文", + "FRENCH": "Français", + "ITALIAN": "Italiano", + "TURKISH": "Türkçe", + "JAPANESE": "日本語", + "DUTCH": "Nederlands", + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" + }, + "YES": "Tak", + "NO": "Nie", + "MENU": { + "OPEN": "Otwórz menu", + "SUPPORT_ARIA": "Wsparcie IPTVnator na GitHubie", + "SETTINGS": "Ustawienia", + "SETTINGS_ARIA": "Otwórz ustawienia", + "BUG_REPORT": "Zgłoś błąd", + "WHAT_IS_NEW": "Co nowego", + "ABOUT": "O aplikacji", + "ABOUT_ARIA": "Informacje o aplikacji", + "SUPPORT_PROJECT": "Wesprzyj projekt" + }, + "ABOUT": { + "TITLE": "O IPTVnator", + "DESCRIPTION": "Wieloplatformowa aplikacja do odtwarzania IPTV z wieloma funkcjami, takimi jak obsługa list odtwarzania m3u i m3u8, ulubione, przewodnik TV, archiwum TV/catchup i inne.", + "VERSION": "Wersja", + "GITHUB_TOOLTIP": "Repozytorium ITPVnator na GitHubie", + "BUY_ME_A_COFFEE_TOOLTIP": "Postaw mi kawę", + "TWITTER_TOOLTIP": "Udostępnij na Twitterze" + }, + "UPDATE_AVAILABLE": "Dostępna aktualizacja", + "REFRESH": "Odśwież", + "XTREAM": { + "PLAY": "Odtwórz", + "NAME": "Nazwa", + "RELEASE_DATE": "Data wydania", + "GENRE": "Gatunek", + "COUNTRY": "Kraj", + "ACTORS": "Aktorzy", + "DIRECTOR": "Reżyser", + "DURATION": "Czas trwania", + "CAST": "Obsada", + "EPISODE_RUN_TIME": "Czas trwania odcinka", + "RATING": "Ocena", + "IMDB_RATING": "Ocena IMDB", + "KINOPOISK_RATING": "Ocena Kinopoisk", + "DESCRIPTION": "Opis", + "YEAR": "Rok", + "AGE": "Wiek", + "YOUTUBE_TRAILER": "Zwiastun YouTube", + "EPISODE": "Odcinek" + }, + "PORTALS": { + "ALL_CATEGORIES": "Wszystkie kategorie", + "MY_FAVORITES": "Moje ulubione", + "ADD_TO_FAVORITES": "Dodaj do ulubionych", + "REMOVE_FROM_FAVORITES": "Usuń z ulubionych", + "REMOVED_FROM_FAVORITES": "Usunięto z ulubionych", + "ADDED_TO_FAVORITES": "Dodano do ulubionych", + "ERROR_VIEW": { + "ACCOUNT_EXPIRED": { + "TITLE": "Konto wygasło", + "DESCRIPTION": "To konto wygasło. Sprawdź dane uwierzytelniające w ustawieniach listy odtwarzania lub usuń ją." + }, + "UNAUTHORIZED": { + "TITLE": "Nieautoryzowany", + "DESCRIPTION": "Sprawdź dane uwierzytelniające w ustawieniach listy odtwarzania lub usuń ją." + }, + "NOT_FOUND": { + "TITLE": "Nie znaleziono portalu", + "DESCRIPTION": "Sprawdź dane uwierzytelniające i URL portalu w ustawieniach listy odtwarzania lub usuń ją." + }, + "EMPTY_CATEGORY": { + "TITLE": "Pusta kategoria", + "DESCRIPTION": "Ta kategoria nie zawiera treści, wybierz inną kategorię lub zmień typ treści" + }, + "UNKNOWN_ERROR": { + "TITLE": "Coś poszło nie tak", + "DESCRIPTION": "Nieznany błąd, spróbuj ponownie później" + }, + "PLAYLIST_SETTINGS": "Ustawienia listy odtwarzania", + "HOME": "Strona główna", + "DELETE": "Usuń" + }, + "EMPTY_LIST_VIEW": { + "NO_SEARCH_RESULTS": "Nic nie znaleziono, spróbuj zmienić zapytanie wyszukiwania" + }, + "STREAM_URL_COPIED": "URL strumienia skopiowany do schowka", + "COPY_STREAM_URL": "Kopiuj URL strumienia" + }, + "INFORMATION": "Informacje", + "REMOTE_CONTROL": { + "TITLE": "Zdalne sterowanie", + "UP_CHANNEL": "Kanał w górę", + "DOWN_CHANNEL": "Kanał w dół", + "HEADER": "Zdalne sterowanie IPTVNator", + "FOOTER": "Zdalne sterowanie IPTVNator" + } +} \ No newline at end of file diff --git a/src/assets/i18n/ru.json b/src/assets/i18n/ru.json index 9fe8c4d99..d6cf654c0 100644 --- a/src/assets/i18n/ru.json +++ b/src/assets/i18n/ru.json @@ -198,7 +198,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "NO": "Нет", "YES": "Да", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index 9dccfcff4..dbbef1109 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -210,7 +210,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "Evet", "NO": "Hayır", diff --git a/src/assets/i18n/zh.json b/src/assets/i18n/zh.json index 166dc3d7a..f654115b2 100644 --- a/src/assets/i18n/zh.json +++ b/src/assets/i18n/zh.json @@ -174,7 +174,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "是", "NO": "否", diff --git a/src/assets/i18n/zhtw.json b/src/assets/i18n/zhtw.json index 43512b7c4..f0b35e70c 100644 --- a/src/assets/i18n/zhtw.json +++ b/src/assets/i18n/zhtw.json @@ -177,7 +177,8 @@ "TURKISH": "Türkçe", "JAPANESE": "日本語", "DUTCH": "Nederlands", - "BELARUSIAN": "Беларуская" + "BELARUSIAN": "Беларуская", + "POLISH": "Polski" }, "YES": "是", "NO": "否", From 47c67b306ae584b25ce8de75154d82dc6e2780db Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 4 Apr 2025 20:24:08 +0200 Subject: [PATCH 07/11] fix(epg): get epg for channels by name --- .../channel-list-container.component.ts | 2 +- .../channel-list-item.component.ts | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/app/player/components/channel-list-container/channel-list-container.component.ts b/src/app/player/components/channel-list-container/channel-list-container.component.ts index 65d84d4a8..e38d2e4ab 100644 --- a/src/app/player/components/channel-list-container/channel-list-container.component.ts +++ b/src/app/player/components/channel-list-container/channel-list-container.component.ts @@ -133,7 +133,7 @@ export class ChannelListContainerComponent { this.selected = channel; this.store.dispatch(PlaylistActions.setActiveChannel({ channel })); - const epgChannelId = channel?.tvg?.id?.trim() || channel?.name.trim(); + const epgChannelId = channel?.name.trim(); if (epgChannelId) { this.epgService.getChannelPrograms(epgChannelId); diff --git a/src/app/player/components/channel-list-container/channel-list-item/channel-list-item.component.ts b/src/app/player/components/channel-list-container/channel-list-item/channel-list-item.component.ts index d2c85a192..007a95004 100644 --- a/src/app/player/components/channel-list-container/channel-list-item/channel-list-item.component.ts +++ b/src/app/player/components/channel-list-container/channel-list-item/channel-list-item.component.ts @@ -1,11 +1,10 @@ import { DragDropModule } from '@angular/cdk/drag-drop'; -import { CommonModule } from '@angular/common'; +import { NgIf } from '@angular/common'; import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDividerModule } from '@angular/material/divider'; -import { MatIconModule } from '@angular/material/icon'; +import { MatIconButton } from '@angular/material/button'; +import { MatIcon } from '@angular/material/icon'; import { MatListModule } from '@angular/material/list'; -import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatTooltip } from '@angular/material/tooltip'; import { TranslatePipe } from '@ngx-translate/core'; @Component({ @@ -49,13 +48,12 @@ import { TranslatePipe } from '@ngx-translate/core'; `, imports: [ - CommonModule, DragDropModule, - MatButtonModule, - MatDividerModule, - MatIconModule, + MatIcon, + MatIconButton, MatListModule, - MatTooltipModule, + MatTooltip, + NgIf, TranslatePipe, ], }) From 4872d8ec8726ab34d7347d573c81c34a6d492aec Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 4 Apr 2025 20:24:35 +0200 Subject: [PATCH 08/11] fix(multi-epg): get epg for channels by name --- .../components/multi-epg/multi-epg-container.component.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/app/player/components/multi-epg/multi-epg-container.component.ts b/src/app/player/components/multi-epg/multi-epg-container.component.ts index 427224d9b..16f81c483 100644 --- a/src/app/player/components/multi-epg/multi-epg-container.component.ts +++ b/src/app/player/components/multi-epg/multi-epg-container.component.ts @@ -161,10 +161,7 @@ export class MultiEpgContainerComponent try { const channelNames = this._playlistChannels - .map( - (channel) => - channel.tvg?.id?.trim() ?? channel.name?.trim() ?? '' - ) + .map((channel) => channel.name?.trim() ?? '') .filter((name) => name !== ''); console.log('Requesting EPG data:'); From b9fae1e49310941b47e47deb3b3de0682d1e77c3 Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 4 Apr 2025 20:25:26 +0200 Subject: [PATCH 09/11] feat(permissions): allow fetching of local files --- src-tauri/capabilities/default.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index a5eaf2876..973c9d585 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -30,6 +30,12 @@ }, { "url": "https://*:**" + }, + { + "url": "file://**" + }, + { + "url": "file:///**" } ] }, From e5a1684feaedfaecad93757e05cae431e47aadb1 Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 4 Apr 2025 20:25:46 +0200 Subject: [PATCH 10/11] feat(epg): fetch epg from local files --- src-tauri/src/epg.rs | 49 +++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src-tauri/src/epg.rs b/src-tauri/src/epg.rs index 263f06a69..b4eca6a03 100644 --- a/src-tauri/src/epg.rs +++ b/src-tauri/src/epg.rs @@ -78,19 +78,44 @@ pub async fn fetch_and_parse_epg(url: String) -> Result<(), Box Result> { info!("Starting EPG fetch from URL: {}", url); - // Fetch content - let client = reqwest::Client::new(); - let content = if url.ends_with(".gz") { - info!("Fetching and decompressing gzipped EPG data..."); - let bytes = client.get(&url).send().await?.bytes().await?; - let mut decoder = GzDecoder::new(&bytes[..]); - let mut string = String::new(); - decoder.read_to_string(&mut string)?; - info!("Successfully decompressed EPG data"); - string + // Get content based on URL type + let content = if url.starts_with("file://") { + info!("Reading EPG data from local file..."); + let file_path = url.strip_prefix("file://").unwrap_or(&url); + let file_content = std::fs::read_to_string(file_path) + .or_else(|_| { + // If regular read fails, try reading as gzip + if file_path.ends_with(".gz") { + info!("Attempting to decompress local gzipped file..."); + let file = std::fs::File::open(file_path)?; + let mut decoder = GzDecoder::new(file); + let mut content = String::new(); + decoder.read_to_string(&mut content)?; + Ok(content) + } else { + Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Failed to read file", + )) + } + })?; + info!("Successfully read local EPG file"); + file_content } else { - info!("Fetching EPG data..."); - client.get(&url).send().await?.text().await? + // Fetch content from remote URL + let client = reqwest::Client::new(); + if url.ends_with(".gz") { + info!("Fetching and decompressing gzipped EPG data..."); + let bytes = client.get(&url).send().await?.bytes().await?; + let mut decoder = GzDecoder::new(&bytes[..]); + let mut string = String::new(); + decoder.read_to_string(&mut string)?; + info!("Successfully decompressed EPG data"); + string + } else { + info!("Fetching EPG data..."); + client.get(&url).send().await?.text().await? + } }; info!("Parsing EPG XML data..."); From fac3a9d49e8168724249b1265bd66d587b5fe019 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sat, 5 Apr 2025 15:07:04 +0200 Subject: [PATCH 11/11] chore: bump version to 1.0.0-beta.6 --- package-lock.json | 2 +- package.json | 2 +- src-tauri/Cargo.lock | 9 ++++++++- src-tauri/Cargo.toml | 4 ++-- src-tauri/tauri.conf.json | 22 ++++++++++++++++------ 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 512282356..fcf0d45b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iptvnator", - "version": "1.0.0-beta.5", + "version": "1.0.0-beta.6", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index 9c9e1c3ea..f367194d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iptvnator", - "version": "1.0.0-beta.5", + "version": "1.0.0-beta.6", "description": "IPTV player application.", "homepage": "https://github.com/4gray/iptvnator", "author": { diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 6298c69e8..492ab7124 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "IPTVnator" -version = "1.0.0-beta.5" +version = "1.0.0-beta.6" dependencies = [ "chrono", "fix-path-env", @@ -1899,6 +1899,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + [[package]] name = "httparse" version = "1.10.1" @@ -4986,6 +4992,7 @@ dependencies = [ "gtk", "heck 0.5.0", "http 1.2.0", + "http-range", "jni", "libc", "log", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d0ad1d1c3..a7ad47279 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "IPTVnator" -version = "1.0.0-beta.5" +version = "1.0.0-beta.6" description = "IPTVnator" authors = ["4gray"] license = "MIT" @@ -21,7 +21,7 @@ tauri-build = { version = "2", features = [] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } log = "0.4" -tauri = { version = "2.2.0", features = ["macos-private-api"] } +tauri = { version = "2.2.0", features = [ "protocol-asset", "macos-private-api"] } tauri-plugin-log = "2" tauri-plugin-http = {version = "2", features = ["unsafe-headers"] } tauri-plugin-shell = "2" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 943b022d3..a31df0a8b 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "iptvnator", - "version": "1.0.0-5", + "version": "1.0.0-6", "identifier": "com.4gray.dev", "build": { "frontendDist": "../dist/browser", @@ -43,7 +43,8 @@ "https:", "http:", "'unsafe-eval'", - "'unsafe-inline'" + "'unsafe-inline'", + "file:" ], "img-src": [ "'self'", @@ -51,22 +52,27 @@ "asset:", "https:", "http:", - "blob:" + "blob:", + "file:", + "'unsafe-eval'", + "'unsafe-inline'" ], - "media-src": ["'self'", "https:", "http:", "blob:", "data:"], + "media-src": ["'self'", "https:", "http:", "blob:", "data:", "file:"], "script-src": [ "'self'", "'unsafe-inline'", "'unsafe-eval'", "tauri:", - "asset:" + "asset:", + "file:" ], "style-src": [ "'self'", "'unsafe-inline'", "https:", "http:", - "https://fonts.googleapis.com" + "https://fonts.googleapis.com", + "file:" ], "font-src": ["'self'", "https://fonts.gstatic.com", "data:"], "connect-src": [ @@ -80,6 +86,10 @@ ], "frame-src": ["'self'", "https:", "http:", "blob:", "data:"], "worker-src": ["'self'", "blob:", "data:"] + }, + "assetProtocol": { + "enable": true, + "scope": ["*/**"] } } },