mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-23 09:29:41 +02:00
Merge remote-tracking branch 'origin/main' into dev
This commit is contained in:
@@ -167,7 +167,7 @@
|
|||||||
"lastUpdateCheckX": "Vérification de la dernière mise à jour : {}",
|
"lastUpdateCheckX": "Vérification de la dernière mise à jour : {}",
|
||||||
"remove": "Retirer",
|
"remove": "Retirer",
|
||||||
"yesMarkUpdated": "Oui, marquer comme mis à jour",
|
"yesMarkUpdated": "Oui, marquer comme mis à jour",
|
||||||
"fdroid": "F-Droïde Officiel",
|
"fdroid": "F-Droid Officiel",
|
||||||
"appIdOrName": "ID ou nom de l'application",
|
"appIdOrName": "ID ou nom de l'application",
|
||||||
"appId": "ID de l'application",
|
"appId": "ID de l'application",
|
||||||
"appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom",
|
"appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom",
|
||||||
|
@@ -281,14 +281,14 @@
|
|||||||
"parallelDownloads": "Párhuzamos letöltéseket enged",
|
"parallelDownloads": "Párhuzamos letöltéseket enged",
|
||||||
"installMethod": "Telepítési mód",
|
"installMethod": "Telepítési mód",
|
||||||
"normal": "Normál",
|
"normal": "Normál",
|
||||||
"root": "Gyökér",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "A Shizuku nem fut",
|
"shizukuBinderNotFound": "A Shizuku nem fut",
|
||||||
"useSystemFont": "Használja a rendszer betűtípusát",
|
"useSystemFont": "Használja a rendszer betűtípusát",
|
||||||
"systemFontError": "Hiba a rendszer betűtípusának betöltésekor: {}",
|
"systemFontError": "Hiba a rendszer betűtípusának betöltésekor: {}",
|
||||||
"useVersionCodeAsOSVersion": "Az app verziókód használata a rendszer által észlelt verzióként",
|
"useVersionCodeAsOSVersion": "Az app verziókód használata a rendszer által észlelt verzióként",
|
||||||
"requestHeader": "Kérelem fejléc",
|
"requestHeader": "Kérelem fejléc",
|
||||||
"useLatestAssetDateAsReleaseDate": "Használja a legújabb tartalomfeltöltést megjelenési dátumként",
|
"useLatestAssetDateAsReleaseDate": "Használja a legújabb tartalomfeltöltést megjelenési dátumként",
|
||||||
"defaultPseudoVersioningMethod": "Alapértelmezett álversziós módszer",
|
"defaultPseudoVersioningMethod": "Alapértelmezett álverziós módszer",
|
||||||
"partialAPKHash": "Részleges APK Hash",
|
"partialAPKHash": "Részleges APK Hash",
|
||||||
"APKLinkHash": "APK Link Hash",
|
"APKLinkHash": "APK Link Hash",
|
||||||
"directAPKLink": "Közvetlen APK Link",
|
"directAPKLink": "Közvetlen APK Link",
|
||||||
|
359
assets/translations/uk.json
Normal file
359
assets/translations/uk.json
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
{
|
||||||
|
"invalidURLForSource": "Неправильна URL-адреса для джерела застосунку {}",
|
||||||
|
"noReleaseFound": "Не вдалося знайти відповідне видання",
|
||||||
|
"noVersionFound": "Не вдалося визначити версію видання",
|
||||||
|
"urlMatchesNoSource": "URL не відповідає відомому джерелу",
|
||||||
|
"cantInstallOlderVersion": "Не можна встановити старішу версію застосунку",
|
||||||
|
"appIdMismatch": "Ідентифікатор пакета, завантажений, не відповідає ідентифікатору існуючого застосунку",
|
||||||
|
"functionNotImplemented": "Цей клас не реалізував цю функцію",
|
||||||
|
"placeholder": "Заповнювач",
|
||||||
|
"someErrors": "Виникла деяка помилка",
|
||||||
|
"unexpectedError": "Неочікувана помилка",
|
||||||
|
"ok": "Добре",
|
||||||
|
"and": "та",
|
||||||
|
"githubPATLabel": "Персональний ключ доступу GitHub (збільшує обмеження на швидкість)",
|
||||||
|
"includePrereleases": "Включити попередні видання",
|
||||||
|
"fallbackToOlderReleases": "Повернутися до старіших видань",
|
||||||
|
"filterReleaseTitlesByRegEx": "Фільтрувати заголовки видань за допомогою регулярного виразу",
|
||||||
|
"invalidRegEx": "Неприпустимий регулярний вираз",
|
||||||
|
"noDescription": "Немає опису",
|
||||||
|
"cancel": "Скасувати",
|
||||||
|
"continue": "Продовжити",
|
||||||
|
"requiredInBrackets": "(Обов'язково)",
|
||||||
|
"dropdownNoOptsError": "ПОМИЛКА: В ВИПАДАЮЧОМУ СПИСКУ МАЄ БУТИ ХОЧА Б ОДИН ЕЛЕМЕНТ",
|
||||||
|
"colour": "Колір",
|
||||||
|
"githubStarredRepos": "Відзначені репозиторії GitHub",
|
||||||
|
"uname": "Ім'я користувача",
|
||||||
|
"wrongArgNum": "Надано неправильну кількість аргументів",
|
||||||
|
"xIsTrackOnly": "{} - тільки відстежування",
|
||||||
|
"source": "Джерело",
|
||||||
|
"app": "застосунок",
|
||||||
|
"appsFromSourceAreTrackOnly": "Додатки з цього джерела є лише для відстежування.",
|
||||||
|
"youPickedTrackOnly": "Ви вибрали опцію лише для відстежування.",
|
||||||
|
"trackOnlyAppDescription": "Застосунок буде відстежуватися для оновлень, але Obtainium не зможе його завантажити або встановити.",
|
||||||
|
"cancelled": "Скасовано",
|
||||||
|
"appAlreadyAdded": "Застосунок вже додано",
|
||||||
|
"alreadyUpToDateQuestion": "Застосунок вже оновлено?",
|
||||||
|
"addApp": "Додати Застосунок",
|
||||||
|
"appSourceURL": "URL-адреса джерела застосунку",
|
||||||
|
"error": "Помилка",
|
||||||
|
"add": "Додати",
|
||||||
|
"searchSomeSourcesLabel": "Пошук (Лише деякі джерела)",
|
||||||
|
"search": "Пошук",
|
||||||
|
"additionalOptsFor": "Додаткові опції для {}",
|
||||||
|
"supportedSources": "Підтримувані джерела",
|
||||||
|
"trackOnlyInBrackets": "(Тільки для відстеження)",
|
||||||
|
"searchableInBrackets": "(Можливий пошук)",
|
||||||
|
"appsString": "Додатки",
|
||||||
|
"noApps": "Додатків немає",
|
||||||
|
"noAppsForFilter": "Додатків для фільтрації немає",
|
||||||
|
"byX": "За {}",
|
||||||
|
"percentProgress": "Прогрес: {}%",
|
||||||
|
"pleaseWait": "Будь ласка, зачекайте",
|
||||||
|
"updateAvailable": "Доступно оновлення",
|
||||||
|
"notInstalled": "Не встановлено",
|
||||||
|
"pseudoVersion": "псевдо-версія",
|
||||||
|
"selectAll": "Вибрати все",
|
||||||
|
"deselectX": "Скасувати вибір {}",
|
||||||
|
"xWillBeRemovedButRemainInstalled": "{} буде видалено з Obtainium, але залишиться встановленим на пристрої.",
|
||||||
|
"removeSelectedAppsQuestion": "Видалити вибрані додатки?",
|
||||||
|
"removeSelectedApps": "Видалити вибрані додатки",
|
||||||
|
"updateX": "Оновити {}",
|
||||||
|
"installX": "Встановити {}",
|
||||||
|
"markXTrackOnlyAsUpdated": "Позначити {}\n(Тільки відстежування)\nяк оновлено",
|
||||||
|
"changeX": "Змінити {}",
|
||||||
|
"installUpdateApps": "Встановити/Оновити додатки",
|
||||||
|
"installUpdateSelectedApps": "Встановити/Оновити вибрані додатки",
|
||||||
|
"markXSelectedAppsAsUpdated": "Позначити {} вибрані додатки як оновлені?",
|
||||||
|
"no": "Ні",
|
||||||
|
"yes": "Так",
|
||||||
|
"markSelectedAppsUpdated": "Позначити вибрані додатки як оновлені",
|
||||||
|
"pinToTop": "Закріпити угорі",
|
||||||
|
"unpinFromTop": "Відкріпити зверху",
|
||||||
|
"resetInstallStatusForSelectedAppsQuestion": "Скинути статус встановлення для вибраних додатків?",
|
||||||
|
"installStatusOfXWillBeResetExplanation": "Статус встановлення будь-яких вибраних додатків буде скинутий.\n\nЦе може допомогти, коли версія застосунку, відображена в Obtainium, є неправильною через невдалі оновлення або інші проблеми.",
|
||||||
|
"customLinkMessage": "Ці посилання працюють на пристроях з встановленим Obtainium",
|
||||||
|
"shareAppConfigLinks": "Поділитися посиланнями на конфігурацію Застосунку як HTML",
|
||||||
|
"shareSelectedAppURLs": "Поділитися вибраними URL-адресами додатків",
|
||||||
|
"resetInstallStatus": "Скинути статус встановлення",
|
||||||
|
"more": "Більше",
|
||||||
|
"removeOutdatedFilter": "Видалити фільтр застарілих додатків",
|
||||||
|
"showOutdatedOnly": "Показати лише застарілі додатки",
|
||||||
|
"filter": "Фільтр",
|
||||||
|
"filterApps": "Фільтрувати додатки",
|
||||||
|
"appName": "Назва застосунку",
|
||||||
|
"author": "Автор",
|
||||||
|
"upToDateApps": "Актуальні додатки",
|
||||||
|
"nonInstalledApps": "Невстановлені додатки",
|
||||||
|
"importExport": "Імпорт/Експорт",
|
||||||
|
"settings": "Налаштування",
|
||||||
|
"exportedTo": "Експортовано в {}",
|
||||||
|
"obtainiumExport": "Експорт з Obtainium",
|
||||||
|
"invalidInput": "Недійсний ввід",
|
||||||
|
"importedX": "Імпортовано {}",
|
||||||
|
"obtainiumImport": "Імпорт в Obtainium",
|
||||||
|
"importFromURLList": "Імпорт зі списку URL-адрес",
|
||||||
|
"searchQuery": "Пошуковий запит",
|
||||||
|
"appURLList": "Список URL-адрес додатків",
|
||||||
|
"line": "Лінія",
|
||||||
|
"searchX": "Пошук {}",
|
||||||
|
"noResults": "Результати відсутні",
|
||||||
|
"importX": "Імпорт {}",
|
||||||
|
"importedAppsIdDisclaimer": "Імпортовані додатки можуть неправильно відображатися як \"Не встановлені\".\nДля виправлення цього перевстановіть їх через Obtainium.\nЦе не повинно вплинути на дані додатків.\n\nПов'язано лише з URL-адресами та імпортом від третіх сторін.",
|
||||||
|
"importErrors": "Помилки імпорту",
|
||||||
|
"importedXOfYApps": "Імпортовано {} з {} додатків.",
|
||||||
|
"followingURLsHadErrors": "Помилки в наступних URL-адресах:",
|
||||||
|
"selectURL": "Вибрати URL",
|
||||||
|
"selectURLs": "Вибрати URL-адреси",
|
||||||
|
"pick": "Вибрати",
|
||||||
|
"theme": "Тема",
|
||||||
|
"dark": "Темна",
|
||||||
|
"light": "Світла",
|
||||||
|
"followSystem": "Дотримуватися системи",
|
||||||
|
"useBlackTheme": "Використовувати чисто чорну темну тему",
|
||||||
|
"appSortBy": "Сортувати додатки за",
|
||||||
|
"authorName": "Автор/Назва",
|
||||||
|
"nameAuthor": "Назва/Автор",
|
||||||
|
"asAdded": "За додаванням",
|
||||||
|
"appSortOrder": "Порядок сортування додатків",
|
||||||
|
"ascending": "За зростанням",
|
||||||
|
"descending": "За спаданням",
|
||||||
|
"bgUpdateCheckInterval": "Інтервал перевірки оновлень у фоновому режимі",
|
||||||
|
"neverManualOnly": "Ніколи - Тільки вручну",
|
||||||
|
"appearance": "Вигляд",
|
||||||
|
"showWebInAppView": "Показати джерело застосунку у вигляді веб-сторінки",
|
||||||
|
"pinUpdates": "Закріпити оновлення у верхній частині вигляду додатків",
|
||||||
|
"updates": "Оновлення",
|
||||||
|
"sourceSpecific": "Певне джерело",
|
||||||
|
"appSource": "Джерело застосунку",
|
||||||
|
"noLogs": "Немає логів",
|
||||||
|
"appLogs": "Лог застосунку",
|
||||||
|
"close": "Закрити",
|
||||||
|
"share": "Поділитися",
|
||||||
|
"appNotFound": "Застосунок не знайдено",
|
||||||
|
"obtainiumExportHyphenatedLowercase": "експорт з Obtainium",
|
||||||
|
"pickAnAPK": "Вибрати APK",
|
||||||
|
"appHasMoreThanOnePackage": "{} має більше одного пакету:",
|
||||||
|
"deviceSupportsXArch": "Ваш пристрій підтримує архітектуру процесора {}.",
|
||||||
|
"deviceSupportsFollowingArchs": "Ваш пристрій підтримує наступні архітектури процесора:",
|
||||||
|
"warning": "Попередження",
|
||||||
|
"sourceIsXButPackageFromYPrompt": "Джерело застосунку - '{}' але пакет випуску походить з '{}'. Продовжити?",
|
||||||
|
"updatesAvailable": "Доступні оновлення",
|
||||||
|
"updatesAvailableNotifDescription": "Повідомляє користувача, що доступні оновлення для одного чи декількох додатків, які відстежує Obtainium",
|
||||||
|
"noNewUpdates": "Немає нових оновлень.",
|
||||||
|
"xHasAnUpdate": "{} має оновлення.",
|
||||||
|
"appsUpdated": "Додатки оновлено",
|
||||||
|
"appsUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного чи декількох додатків було застосовано в фоновому режимі",
|
||||||
|
"xWasUpdatedToY": "{} було оновлено до {}.",
|
||||||
|
"errorCheckingUpdates": "Помилка перевірки оновлень",
|
||||||
|
"errorCheckingUpdatesNotifDescription": "Повідомлення, яке з'являється, коли перевірка оновлень в фоновому режимі завершується невдачею",
|
||||||
|
"appsRemoved": "Додатки видалено",
|
||||||
|
"appsRemovedNotifDescription": "Повідомляє користувача, що один чи декілька додатків були видалені через помилки при завантаженні",
|
||||||
|
"xWasRemovedDueToErrorY": "{} було видалено через цю помилку: {}",
|
||||||
|
"completeAppInstallation": "Завершення установки застосунку",
|
||||||
|
"obtainiumMustBeOpenToInstallApps": "Для встановлення додатків Obtainium має бути відкритий",
|
||||||
|
"completeAppInstallationNotifDescription": "Прохання користувача повернутися до Obtainium для завершення установки застосунку",
|
||||||
|
"checkingForUpdates": "Перевірка оновлень",
|
||||||
|
"checkingForUpdatesNotifDescription": "Тимчасове повідомлення, яке з'являється при перевірці оновлень",
|
||||||
|
"pleaseAllowInstallPerm": "Будь ласка, дозвольте Obtainium встановлювати додатки",
|
||||||
|
"trackOnly": "Тільки відстеження",
|
||||||
|
"errorWithHttpStatusCode": "Помилка {} HTTP-коду",
|
||||||
|
"versionCorrectionDisabled": "Виправлення версії вимкнено (здається, плагін не працює)",
|
||||||
|
"unknown": "Невідомо",
|
||||||
|
"none": "Нічого",
|
||||||
|
"never": "Ніколи",
|
||||||
|
"latestVersionX": "Остання версія: {}",
|
||||||
|
"installedVersionX": "Встановлено: {}",
|
||||||
|
"lastUpdateCheckX": "Остання перевірка оновлень: {}",
|
||||||
|
"remove": "Видалити",
|
||||||
|
"yesMarkUpdated": "Так, позначити як оновлене",
|
||||||
|
"fdroid": "F-Droid Офіційний",
|
||||||
|
"appIdOrName": "Ідентифікатор або назва застосунку",
|
||||||
|
"appId": "Ідентифікатор застосунку",
|
||||||
|
"appWithIdOrNameNotFound": "Застосунок з таким ідентифікатором або назвою не знайдено",
|
||||||
|
"reposHaveMultipleApps": "Сховища можуть містити кілька додатків",
|
||||||
|
"fdroidThirdPartyRepo": "F-Droid Стороннє сховище",
|
||||||
|
"steamMobile": "Мобільний Steam",
|
||||||
|
"steamChat": "Чат Steam",
|
||||||
|
"install": "Встановити",
|
||||||
|
"markInstalled": "Позначити як встановлене",
|
||||||
|
"update": "Оновити",
|
||||||
|
"markUpdated": "Позначити як оновлене",
|
||||||
|
"additionalOptions": "Додаткові опції",
|
||||||
|
"disableVersionDetection": "Вимкнути визначення версії",
|
||||||
|
"noVersionDetectionExplanation": "Цю опцію слід використовувати лише для додатків, де визначення версії працює неправильно.",
|
||||||
|
"downloadingX": "Завантаження {}",
|
||||||
|
"downloadNotifDescription": "Повідомляє користувача про прогрес завантаження застосунку",
|
||||||
|
"noAPKFound": "APK не знайдено",
|
||||||
|
"noVersionDetection": "Визначення версії відключено",
|
||||||
|
"categorize": "Категоризувати",
|
||||||
|
"categories": "Категорії",
|
||||||
|
"category": "Категорія",
|
||||||
|
"noCategory": "Без категорії",
|
||||||
|
"noCategories": "Немає категорій",
|
||||||
|
"deleteCategoriesQuestion": "Видалити категорії?",
|
||||||
|
"categoryDeleteWarning": "Усі додатки у видалених категоріях будуть переведені у некатегоризовані.",
|
||||||
|
"addCategory": "Додати категорію",
|
||||||
|
"label": "Мітка",
|
||||||
|
"language": "Мова",
|
||||||
|
"copiedToClipboard": "Скопійовано в буфер обміну",
|
||||||
|
"storagePermissionDenied": "Відмовлено у дозволі на доступ до сховища",
|
||||||
|
"selectedCategorizeWarning": "Це замінить будь-які існуючі налаштування категорій для вибраних додатків.",
|
||||||
|
"filterAPKsByRegEx": "Фільтрувати APK за регулярним виразом",
|
||||||
|
"removeFromObtainium": "Видалити з Obtainium",
|
||||||
|
"uninstallFromDevice": "Видалити з пристрою",
|
||||||
|
"onlyWorksWithNonVersionDetectApps": "Працює лише з застосунками з вимкненим визначенням версії.",
|
||||||
|
"releaseDateAsVersion": "Використовувати дату випуску як рядок версії",
|
||||||
|
"releaseDateAsVersionExplanation": "Цю опцію слід використовувати лише для додатків, де визначення версії працює неправильно, але є дата випуску.",
|
||||||
|
"changes": "Зміни",
|
||||||
|
"releaseDate": "Дата випуску",
|
||||||
|
"importFromURLsInFile": "Імпорт з URL-адрес у файлі (наприклад, OPML)",
|
||||||
|
"versionDetectionExplanation": "Порівняти рядок версії з версією, визначеною операційною системою",
|
||||||
|
"versionDetection": "Визначення версії",
|
||||||
|
"standardVersionDetection": "Стандартне визначення версії",
|
||||||
|
"groupByCategory": "Групувати за категоріями",
|
||||||
|
"autoApkFilterByArch": "Спробувати фільтрувати APK за архітектурою ЦП, якщо можливо",
|
||||||
|
"overrideSource": "Перевизначити джерело",
|
||||||
|
"dontShowAgain": "Не показувати це знову",
|
||||||
|
"dontShowTrackOnlyWarnings": "Не показувати попередження про 'Тільки відстеження'",
|
||||||
|
"dontShowAPKOriginWarnings": "Не показувати попередження про походження APK",
|
||||||
|
"moveNonInstalledAppsToBottom": "Перемістити невстановлені додатки вниз у перегляді додатків",
|
||||||
|
"gitlabPATLabel": "Особистий токен GitLab (Увімкнення пошуку та краще виявлення APK)",
|
||||||
|
"about": "Про програму",
|
||||||
|
"requiresCredentialsInSettings": "{} потребує додаткових облікових даних (у налаштуваннях)",
|
||||||
|
"checkOnStart": "Перевірити наявність оновлень при запуску",
|
||||||
|
"tryInferAppIdFromCode": "Спробувати вивести ідентифікатор застосунку з вихідного коду",
|
||||||
|
"removeOnExternalUninstall": "Автоматично видаляти додатки, які було видалено зовнішнім чином",
|
||||||
|
"pickHighestVersionCode": "Автоматично вибрати APK з найвищим кодом версії",
|
||||||
|
"checkUpdateOnDetailPage": "Перевіряти наявність оновлень при відкритті сторінки деталей застосунку",
|
||||||
|
"disablePageTransitions": "Вимкнути анімації переходів між сторінками",
|
||||||
|
"reversePageTransitions": "Зворотні анімації переходів між сторінками",
|
||||||
|
"minStarCount": "Мінімальна кількість зірок",
|
||||||
|
"addInfoBelow": "Додати цю інформацію нижче.",
|
||||||
|
"addInfoInSettings": "Додати цю інформацію у налаштуваннях.",
|
||||||
|
"githubSourceNote": "Лімітування швидкості GitHub можна уникнути, використовуючи ключ API.",
|
||||||
|
"gitlabSourceNote": "Вилучення APK з GitLab може не працювати без ключа API.",
|
||||||
|
"sortByLastLinkSegment": "Сортувати лише за останнім сегментом посилання",
|
||||||
|
"filterReleaseNotesByRegEx": "Фільтрувати примітки до релізу за регулярним виразом",
|
||||||
|
"customLinkFilterRegex": "Фільтр кастомного посилання на APK за регулярним виразом (за замовчуванням '.apk$')",
|
||||||
|
"appsPossiblyUpdated": "Оновлення додатків спробовано",
|
||||||
|
"appsPossiblyUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного або декількох додатків можливо були застосовані в фоновому режимі",
|
||||||
|
"xWasPossiblyUpdatedToY": "{} можливо було оновлено до {}.",
|
||||||
|
"enableBackgroundUpdates": "Увімкнути оновлення в фоновому режимі",
|
||||||
|
"backgroundUpdateReqsExplanation": "Оновлення в фоновому режимі може бути неможливим для всіх додатків.",
|
||||||
|
"backgroundUpdateLimitsExplanation": "Успіх фонової установки може бути визначений лише після відкриття Obtainium.",
|
||||||
|
"verifyLatestTag": "Перевірити тег 'latest'",
|
||||||
|
"intermediateLinkRegex": "Фільтр для 'Проміжного' Посилання для Відвідування",
|
||||||
|
"filterByLinkText": "Фільтрувати посилання за текстом посилання",
|
||||||
|
"intermediateLinkNotFound": "Проміжне посилання не знайдено",
|
||||||
|
"intermediateLink": "Проміжне посилання",
|
||||||
|
"exemptFromBackgroundUpdates": "Виключено з фонових оновлень (якщо ввімкнено)",
|
||||||
|
"bgUpdatesOnWiFiOnly": "Вимкнути фонові оновлення поза Wi-Fi",
|
||||||
|
"autoSelectHighestVersionCode": "Автоматичний вибір APK з найвищим кодом версії",
|
||||||
|
"versionExtractionRegEx": "Регулярний вираз для вилучення рядка версії",
|
||||||
|
"matchGroupToUse": "Група співпадінь для використання в регулярному виразі вилучення версії",
|
||||||
|
"highlightTouchTargets": "Підсвічувати менш очевидні області дотику",
|
||||||
|
"pickExportDir": "Вибрати каталог експорту",
|
||||||
|
"autoExportOnChanges": "Автоматичний експорт при змінах",
|
||||||
|
"includeSettings": "Включити налаштування",
|
||||||
|
"filterVersionsByRegEx": "Фільтрувати версії за регулярним виразом",
|
||||||
|
"trySelectingSuggestedVersionCode": "Спробуйте вибрати запропонований код версії APK",
|
||||||
|
"dontSortReleasesList": "Зберігати порядок випуску з API",
|
||||||
|
"reverseSort": "Зворотне сортування",
|
||||||
|
"takeFirstLink": "Вибрати перше посилання",
|
||||||
|
"skipSort": "Пропустити сортування",
|
||||||
|
"debugMenu": "Меню налагодження",
|
||||||
|
"bgTaskStarted": "Запущено фонове завдання - перевірте журнали.",
|
||||||
|
"runBgCheckNow": "Запустити перевірку оновлень в фоновому режимі зараз",
|
||||||
|
"versionExtractWholePage": "Застосувати регулярний вираз вилучення версії до всієї сторінки",
|
||||||
|
"installing": "Встановлення",
|
||||||
|
"skipUpdateNotifications": "Пропустити сповіщення про оновлення",
|
||||||
|
"updatesAvailableNotifChannel": "Доступні оновлення",
|
||||||
|
"appsUpdatedNotifChannel": "Додатки оновлені",
|
||||||
|
"appsPossiblyUpdatedNotifChannel": "Спроба оновлення додатків",
|
||||||
|
"errorCheckingUpdatesNotifChannel": "Помилка перевірки оновлень",
|
||||||
|
"appsRemovedNotifChannel": "Додатки видалені",
|
||||||
|
"downloadingXNotifChannel": "Завантаження {}",
|
||||||
|
"completeAppInstallationNotifChannel": "Завершення встановлення застосунку",
|
||||||
|
"checkingForUpdatesNotifChannel": "Перевірка оновлень",
|
||||||
|
"onlyCheckInstalledOrTrackOnlyApps": "Перевіряти лише встановлені та додатки, які відстежуються для оновлень",
|
||||||
|
"supportFixedAPKURL": "Підтримка фіксованих посилань на APK",
|
||||||
|
"selectX": "Вибрати {}",
|
||||||
|
"parallelDownloads": "Дозволити паралельні завантаження",
|
||||||
|
"installMethod": "Метод встановлення",
|
||||||
|
"normal": "Звичайний",
|
||||||
|
"root": "Root",
|
||||||
|
"shizukuBinderNotFound": "Сумісний сервіс Shizuku не було знайдено",
|
||||||
|
"useSystemFont": "Використовувати системний шрифт",
|
||||||
|
"systemFontError": "Помилка завантаження системного шрифту: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Використовувати код версії застосунку як версію, визначену операційною системою",
|
||||||
|
"requestHeader": "Заголовок запиту",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Використовувати останню дату завантаження ресурсу як дату випуску",
|
||||||
|
"defaultPseudoVersioningMethod": "Метод за замовчуванням псевдо-версіонування",
|
||||||
|
"partialAPKHash": "Хеш часткового APK",
|
||||||
|
"APKLinkHash": "Хеш посилання на APK",
|
||||||
|
"directAPKLink": "Пряме посилання на APK",
|
||||||
|
"pseudoVersionInUse": "Використовується псевдо-версія",
|
||||||
|
"installed": "Встановлено",
|
||||||
|
"latest": "Остання",
|
||||||
|
"invertRegEx": "Інвертувати регулярний вираз",
|
||||||
|
"note": "Примітка",
|
||||||
|
"selfHostedNote": "Випадаючий список \"{}\" може використовуватися для доступу до власних/призначених для самостійного використання екземплярів будь-якого джерела.",
|
||||||
|
"badDownload": "APK не вдалося розпарсити (несумісний або часткове завантаження)",
|
||||||
|
"removeAppQuestion": {
|
||||||
|
"one": "Видалити Застосунок?",
|
||||||
|
"other": "Видалити додатки?"
|
||||||
|
},
|
||||||
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
|
"one": "Забагато запитів (обмеження швидкості) - повторіть спробу через {} хвилину",
|
||||||
|
"other": "Забагато запитів (обмеження швидкості) - повторіть спробу через {} хвилин"
|
||||||
|
},
|
||||||
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
|
"one": "Помилка перевірки оновлень у фоновому режимі - спробую знову через {} хвилину",
|
||||||
|
"other": "Помилка перевірки оновлень у фоновому режимі - спробую знову через {} хвилин"
|
||||||
|
},
|
||||||
|
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||||
|
"one": "Фонова перевірка оновлень знайшла {} оновлення - сповістить користувача, якщо це необхідно",
|
||||||
|
"other": "Фонова перевірка оновлень знайшла {} оновлень - сповістить користувача, якщо це необхідно"
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"one": "{} Застосунок",
|
||||||
|
"other": "{} Додатки"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"one": "{} URL",
|
||||||
|
"other": "{} URL-адреси"
|
||||||
|
},
|
||||||
|
"minute": {
|
||||||
|
"one": "{} Хвилина",
|
||||||
|
"other": "{} Хвилин"
|
||||||
|
},
|
||||||
|
"hour": {
|
||||||
|
"one": "{} Година",
|
||||||
|
"other": "{} Годин"
|
||||||
|
},
|
||||||
|
"day": {
|
||||||
|
"one": "{} День",
|
||||||
|
"other": "{} Днів"
|
||||||
|
},
|
||||||
|
"clearedNLogsBeforeXAfterY": {
|
||||||
|
"one": "Очищено {n} журнал (до = {before}, після = {after})",
|
||||||
|
"other": "Очищено {n} журналів (до = {before}, після = {after})"
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesAvailable": {
|
||||||
|
"one": "{} і 1 інше Застосунок мають оновлення.",
|
||||||
|
"other": "{} і {} інших додатки мають оновлення."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesInstalled": {
|
||||||
|
"one": "{} і 1 інше Застосунок було оновлено.",
|
||||||
|
"other": "{} і {} інших додатків було оновлено."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
|
"one": "{} і 1 інше Застосунок можливо було оновлено.",
|
||||||
|
"other": "{} і {} інших додатків можливо було оновлено."
|
||||||
|
},
|
||||||
|
"apk": {
|
||||||
|
"one": "{} APK",
|
||||||
|
"other": "{} APK-файли"
|
||||||
|
}
|
||||||
|
}
|
@@ -52,7 +52,7 @@
|
|||||||
"pleaseWait": "请稍候",
|
"pleaseWait": "请稍候",
|
||||||
"updateAvailable": "更新可用",
|
"updateAvailable": "更新可用",
|
||||||
"notInstalled": "未安装",
|
"notInstalled": "未安装",
|
||||||
"pseudoVersion": "伪版本",
|
"pseudoVersion": "虚拟版本号",
|
||||||
"selectAll": "全选",
|
"selectAll": "全选",
|
||||||
"deselectX": "取消选择 {}",
|
"deselectX": "取消选择 {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "“{}”将从 Obtainium 中删除,但仍安装在您的设备中。",
|
"xWillBeRemovedButRemainInstalled": "“{}”将从 Obtainium 中删除,但仍安装在您的设备中。",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"changes": "更新日志",
|
"changes": "更新日志",
|
||||||
"releaseDate": "发行日期",
|
"releaseDate": "发行日期",
|
||||||
"importFromURLsInFile": "从文件中的 URL 导入(如 OPML)",
|
"importFromURLsInFile": "从文件中的 URL 导入(如 OPML)",
|
||||||
"versionDetectionExplanation": "将版本字符串与操作系统检测到的版本进行协调",
|
"versionDetectionExplanation": "使发行版本号与应用定义的版本号一致",
|
||||||
"versionDetection": "版本检测",
|
"versionDetection": "版本检测",
|
||||||
"standardVersionDetection": "常规版本检测",
|
"standardVersionDetection": "常规版本检测",
|
||||||
"groupByCategory": "按类别分组显示",
|
"groupByCategory": "按类别分组显示",
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
"checkOnStart": "启动时进行一次检查",
|
"checkOnStart": "启动时进行一次检查",
|
||||||
"tryInferAppIdFromCode": "尝试从源代码推断应用 ID",
|
"tryInferAppIdFromCode": "尝试从源代码推断应用 ID",
|
||||||
"removeOnExternalUninstall": "自动删除列表中已卸载的应用",
|
"removeOnExternalUninstall": "自动删除列表中已卸载的应用",
|
||||||
"pickHighestVersionCode": "自动选择版本号最高的 APK 文件",
|
"pickHighestVersionCode": "自动选取内部版本号最高的 APK 文件",
|
||||||
"checkUpdateOnDetailPage": "打开应用详情页时进行检查",
|
"checkUpdateOnDetailPage": "打开应用详情页时进行检查",
|
||||||
"disablePageTransitions": "禁用页面过渡动画效果",
|
"disablePageTransitions": "禁用页面过渡动画效果",
|
||||||
"reversePageTransitions": "反转页面过渡动画效果",
|
"reversePageTransitions": "反转页面过渡动画效果",
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
"intermediateLink": "中转链接",
|
"intermediateLink": "中转链接",
|
||||||
"exemptFromBackgroundUpdates": "禁用后台更新(如果已经全局启用)",
|
"exemptFromBackgroundUpdates": "禁用后台更新(如果已经全局启用)",
|
||||||
"bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
|
"bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
|
||||||
"autoSelectHighestVersionCode": "自动选择版本号最高的 APK 文件",
|
"autoSelectHighestVersionCode": "自动选择内部版本号最高的 APK 文件",
|
||||||
"versionExtractionRegEx": "版本号提取规则(正则表达式)",
|
"versionExtractionRegEx": "版本号提取规则(正则表达式)",
|
||||||
"matchGroupToUse": "引用的捕获组",
|
"matchGroupToUse": "引用的捕获组",
|
||||||
"highlightTouchTargets": "突出展示不明显的触摸区域",
|
"highlightTouchTargets": "突出展示不明显的触摸区域",
|
||||||
@@ -285,20 +285,20 @@
|
|||||||
"shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
|
"shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
|
||||||
"useSystemFont": "使用系统字体",
|
"useSystemFont": "使用系统字体",
|
||||||
"systemFontError": "加载系统字体出错:{}",
|
"systemFontError": "加载系统字体出错:{}",
|
||||||
"useVersionCodeAsOSVersion": "使用应用程序版本代码作为操作系统检测到的版本",
|
"useVersionCodeAsOSVersion": "使用内部版本号代替应用定义的版本号",
|
||||||
"requestHeader": "请求标头",
|
"requestHeader": "请求标头",
|
||||||
"useLatestAssetDateAsReleaseDate": "使用最新资产上传作为发布日期",
|
"useLatestAssetDateAsReleaseDate": "使用最近文件上传时间作为发行日期",
|
||||||
"defaultPseudoVersioningMethod": "默认伪版本控制方法",
|
"defaultPseudoVersioningMethod": "默认虚拟版本方案",
|
||||||
"partialAPKHash": "部分 APK 哈希值",
|
"partialAPKHash": "APK 文件散列值片段",
|
||||||
"APKLinkHash": "APK 链接哈希",
|
"APKLinkHash": "APK 文件链接散列值",
|
||||||
"directAPKLink": "直接 APK 链接",
|
"directAPKLink": "APK 文件直链",
|
||||||
"pseudoVersionInUse": "伪版本正在使用",
|
"pseudoVersionInUse": "正在使用虚拟版本号",
|
||||||
"installed": "已安装",
|
"installed": "当前版本",
|
||||||
"latest": "最新的",
|
"latest": "最新版本",
|
||||||
"invertRegEx": "反转正则表达式",
|
"invertRegEx": "反转匹配",
|
||||||
"note": "备注",
|
"note": "备注",
|
||||||
"selfHostedNote": "{}\"下拉菜单可用于访问任何来源的自托管/自定义实例。",
|
"selfHostedNote": "可以通过“{}”下拉菜单来指向任意来源的自托管/自定义实例。",
|
||||||
"badDownload": "无法解析 APK(不兼容或部分下载)",
|
"badDownload": "无法解析 APK 文件(不兼容或文件不完整)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "是否删除应用?",
|
"one": "是否删除应用?",
|
||||||
"other": "是否删除应用?"
|
"other": "是否删除应用?"
|
||||||
|
@@ -2,7 +2,6 @@ import 'dart:convert';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:html/parser.dart';
|
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:obtainium/app_sources/github.dart';
|
import 'package:obtainium/app_sources/github.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
@@ -117,91 +116,58 @@ class GitLab extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
bool fallbackToOlderReleases =
|
// Prepare request params
|
||||||
additionalSettings['fallbackToOlderReleases'] == true;
|
var names = GitHub().getAppNames(standardUrl);
|
||||||
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
|
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
|
||||||
Iterable<APKDetails> apkDetailsList = [];
|
String optionalAuth = (PAT != null) ? 'private_token=$PAT' : '';
|
||||||
if (PAT != null) {
|
|
||||||
var names = GitHub().getAppNames(standardUrl);
|
// Request data from REST API
|
||||||
Response res = await sourceRequest(
|
Response res = await sourceRequest(
|
||||||
'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT',
|
'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?$optionalAuth',
|
||||||
additionalSettings);
|
additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
|
||||||
var json = jsonDecode(res.body) as List<dynamic>;
|
|
||||||
apkDetailsList = json.map((e) {
|
|
||||||
var apkUrlsFromAssets = (e['assets']?['links'] as List<dynamic>? ?? [])
|
|
||||||
.map((e) {
|
|
||||||
return (e['direct_asset_url'] ?? e['url'] ?? '') as String;
|
|
||||||
})
|
|
||||||
.where((s) => s.isNotEmpty)
|
|
||||||
.toList();
|
|
||||||
List<String> uploadedAPKsFromDescription =
|
|
||||||
((e['description'] ?? '') as String)
|
|
||||||
.split('](')
|
|
||||||
.join('\n')
|
|
||||||
.split('.apk)')
|
|
||||||
.join('.apk\n')
|
|
||||||
.split('\n')
|
|
||||||
.where((s) => s.startsWith('/uploads/') && s.endsWith('apk'))
|
|
||||||
.map((s) => '$standardUrl$s')
|
|
||||||
.toList();
|
|
||||||
var apkUrlsSet = apkUrlsFromAssets.toSet();
|
|
||||||
apkUrlsSet.addAll(uploadedAPKsFromDescription);
|
|
||||||
var releaseDateString = e['released_at'] ?? e['created_at'];
|
|
||||||
DateTime? releaseDate = releaseDateString != null
|
|
||||||
? DateTime.parse(releaseDateString)
|
|
||||||
: null;
|
|
||||||
return APKDetails(
|
|
||||||
e['tag_name'] ?? e['name'],
|
|
||||||
getApkUrlsFromUrls(apkUrlsSet.toList()),
|
|
||||||
GitHub().getAppNames(standardUrl),
|
|
||||||
releaseDate: releaseDate);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Response res = await sourceRequest(
|
|
||||||
'$standardUrl/-/tags?format=atom', additionalSettings);
|
|
||||||
if (res.statusCode != 200) {
|
|
||||||
throw getObtainiumHttpError(res);
|
|
||||||
}
|
|
||||||
var standardUri = Uri.parse(standardUrl);
|
|
||||||
var parsedHtml = parse(res.body);
|
|
||||||
apkDetailsList = parsedHtml.querySelectorAll('entry').map((entry) {
|
|
||||||
var entryContent = parse(
|
|
||||||
parseFragment(entry.querySelector('content')!.innerHtml).text);
|
|
||||||
var apkUrls = [
|
|
||||||
...getLinksFromParsedHTML(
|
|
||||||
entryContent,
|
|
||||||
RegExp(
|
|
||||||
'^${standardUri.path.replaceAllMapped(RegExp(r'[.*+?^${}()|[\]\\]'), (x) {
|
|
||||||
return '\\${x[0]}';
|
|
||||||
})}/uploads/[^/]+/[^/]+\\.apk\$',
|
|
||||||
caseSensitive: false),
|
|
||||||
standardUri.origin),
|
|
||||||
// GitLab releases may contain links to externally hosted APKs
|
|
||||||
...getLinksFromParsedHTML(entryContent,
|
|
||||||
RegExp('/[^/]+\\.apk\$', caseSensitive: false), '')
|
|
||||||
.where((element) => Uri.parse(element).host != '')
|
|
||||||
];
|
|
||||||
var entryId = entry.querySelector('id')?.innerHtml;
|
|
||||||
var version =
|
|
||||||
entryId == null ? null : Uri.parse(entryId).pathSegments.last;
|
|
||||||
var releaseDateString = entry.querySelector('updated')?.innerHtml;
|
|
||||||
DateTime? releaseDate = releaseDateString != null
|
|
||||||
? DateTime.parse(releaseDateString)
|
|
||||||
: null;
|
|
||||||
if (version == null) {
|
|
||||||
throw NoVersionError();
|
|
||||||
}
|
|
||||||
return APKDetails(version, getApkUrlsFromUrls(apkUrls),
|
|
||||||
GitHub().getAppNames(standardUrl),
|
|
||||||
releaseDate: releaseDate);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract .apk details from received data
|
||||||
|
Iterable<APKDetails> apkDetailsList = [];
|
||||||
|
var json = jsonDecode(res.body) as List<dynamic>;
|
||||||
|
apkDetailsList = json.map((e) {
|
||||||
|
var apkUrlsFromAssets = (e['assets']?['links'] as List<dynamic>? ?? [])
|
||||||
|
.map((e) {
|
||||||
|
return (e['direct_asset_url'] ?? e['url'] ?? '') as String;
|
||||||
|
})
|
||||||
|
.where((s) => s.isNotEmpty)
|
||||||
|
.toList();
|
||||||
|
List<String> uploadedAPKsFromDescription =
|
||||||
|
((e['description'] ?? '') as String)
|
||||||
|
.split('](')
|
||||||
|
.join('\n')
|
||||||
|
.split('.apk)')
|
||||||
|
.join('.apk\n')
|
||||||
|
.split('\n')
|
||||||
|
.where((s) => s.startsWith('/uploads/') && s.endsWith('apk'))
|
||||||
|
.map((s) => '$standardUrl$s')
|
||||||
|
.toList();
|
||||||
|
var apkUrlsSet = apkUrlsFromAssets.toSet();
|
||||||
|
apkUrlsSet.addAll(uploadedAPKsFromDescription);
|
||||||
|
var releaseDateString = e['released_at'] ?? e['created_at'];
|
||||||
|
DateTime? releaseDate = releaseDateString != null
|
||||||
|
? DateTime.parse(releaseDateString)
|
||||||
|
: null;
|
||||||
|
return APKDetails(
|
||||||
|
e['tag_name'] ?? e['name'],
|
||||||
|
getApkUrlsFromUrls(apkUrlsSet.toList()),
|
||||||
|
GitHub().getAppNames(standardUrl),
|
||||||
|
releaseDate: releaseDate);
|
||||||
|
});
|
||||||
if (apkDetailsList.isEmpty) {
|
if (apkDetailsList.isEmpty) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback procedure
|
||||||
|
bool fallbackToOlderReleases =
|
||||||
|
additionalSettings['fallbackToOlderReleases'] == true;
|
||||||
if (fallbackToOlderReleases) {
|
if (fallbackToOlderReleases) {
|
||||||
if (additionalSettings['trackOnly'] != true) {
|
if (additionalSettings['trackOnly'] != true) {
|
||||||
apkDetailsList =
|
apkDetailsList =
|
||||||
@@ -211,6 +177,7 @@ class GitLab extends AppSource {
|
|||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return apkDetailsList.first;
|
return apkDetailsList.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,7 @@ List<MapEntry<Locale, String>> supportedLocales = const [
|
|||||||
MapEntry(Locale('nl'), 'Nederlands'),
|
MapEntry(Locale('nl'), 'Nederlands'),
|
||||||
MapEntry(Locale('vi'), 'Tiếng Việt'),
|
MapEntry(Locale('vi'), 'Tiếng Việt'),
|
||||||
MapEntry(Locale('tr'), 'Türkçe'),
|
MapEntry(Locale('tr'), 'Türkçe'),
|
||||||
|
MapEntry(Locale('uk'), 'Українська'),
|
||||||
];
|
];
|
||||||
const fallbackLocale = Locale('en');
|
const fallbackLocale = Locale('en');
|
||||||
const localeDir = 'assets/translations';
|
const localeDir = 'assets/translations';
|
||||||
|
Reference in New Issue
Block a user