mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-13 13:26:43 +02:00
Compare commits
128 Commits
v0.14.30-b
...
v0.14.37-b
Author | SHA1 | Date | |
---|---|---|---|
29ea303093 | |||
feff6751ca | |||
ca33fdf752 | |||
fdcdfe89d6 | |||
48ed2115a7 | |||
65988f4e08 | |||
ede65eda6c | |||
5da56acac8 | |||
5720c55301 | |||
ffefa4b30e | |||
80e4986b23 | |||
dc92ccda0a | |||
f9bab18076 | |||
2dec52e221 | |||
7413f693d7 | |||
415460df75 | |||
125a194468 | |||
32e9afbf36 | |||
3eca704f4a | |||
9c95129311 | |||
bf34c1bcdb | |||
284c687d77 | |||
09afb5a3f5 | |||
0138721451 | |||
2d5f610941 | |||
864fa7762b | |||
4fde38ee6a | |||
6cdf0f10d4 | |||
b66592c25f | |||
43616c566d | |||
62f1dc17a0 | |||
0e9a8a937a | |||
9a86b245ce | |||
64533f7a3f | |||
0b7de8d387 | |||
8eba4860fe | |||
b53e2f57e6 | |||
e1e834297b | |||
e37dc6e341 | |||
c91c896854 | |||
7e5dfa03d6 | |||
1a4ec3f049 | |||
756763fcbe | |||
93036c4e67 | |||
15bf972ef6 | |||
bcb4567382 | |||
3890c4ffb9 | |||
c8d82f24a8 | |||
367e740a9c | |||
5b5a51bdad | |||
7fc030a53e | |||
65087fb5f8 | |||
d5e789af3c | |||
45212c699f | |||
03106f3522 | |||
cd2857cb94 | |||
b3ddb8658f | |||
7ae80b6b49 | |||
34f27f9cd4 | |||
4c53b58fd8 | |||
6102ab4be8 | |||
6fcf565974 | |||
77bd16c7cf | |||
7d593080ec | |||
96ea74abeb | |||
e50e3957ec | |||
8cb9420939 | |||
bbb7b8caa2 | |||
cc284f3c9e | |||
bd8aae5fbf | |||
3d162f33df | |||
ff3c37f1b4 | |||
35160ce385 | |||
c8eef91813 | |||
6791b20121 | |||
3311c49236 | |||
5223e58f83 | |||
e0f9fc233d | |||
509bd21655 | |||
5be7229c4b | |||
efd3c461e0 | |||
13aed69f0e | |||
b03675811c | |||
e4beac185e | |||
bdc7d9dd84 | |||
b49d1e0529 | |||
3c0eb48d53 | |||
0d65531ec1 | |||
3848f9822b | |||
e1cdc002b9 | |||
168c1cf1ce | |||
5b142b4401 | |||
9be3d76590 | |||
26971aa109 | |||
18f9049bc6 | |||
53cf253b67 | |||
6d416f45a9 | |||
a34a447164 | |||
d3247a9ec1 | |||
dfb5a2b97f | |||
deae96e191 | |||
b8c0e18bb4 | |||
a083da1546 | |||
2518c70ec8 | |||
6ead8d261c | |||
b5f76a6ebc | |||
5e38bca535 | |||
c39142ee77 | |||
d0174479d7 | |||
aa23267d70 | |||
92f5da306d | |||
8601e2af7a | |||
5d9f31b99e | |||
8b29158d8b | |||
b68cf3c671 | |||
858a50a414 | |||
598df624df | |||
e6da2b73ed | |||
f44424d37a | |||
623804ae68 | |||
ce5639bb98 | |||
99ef6ca861 | |||
43d5a3da27 | |||
30723110af | |||
f76ea9bba5 | |||
6c30bd36d1 | |||
e94e195e73 | |||
869ebd90df |
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@ -22,7 +22,8 @@ jobs:
|
||||
- name: Build APKs
|
||||
run: |
|
||||
sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle
|
||||
flutter build apk && flutter build apk --split-per-abi
|
||||
flutter build apk --flavor normal && flutter build apk --split-per-abi --flavor normal
|
||||
for file in build/app/outputs/flutter-apk/app-*normal*.apk*; do mv "$file" "${file//-normal/}"; done
|
||||
rm ./build/app/outputs/flutter-apk/*.sha1
|
||||
ls -l ./build/app/outputs/flutter-apk/
|
||||
|
||||
|
@ -57,7 +57,20 @@ android {
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
}
|
||||
|
||||
flavorDimensions "flavor"
|
||||
|
||||
productFlavors {
|
||||
normal {
|
||||
dimension "flavor"
|
||||
applicationIdSuffix ""
|
||||
}
|
||||
fdroid {
|
||||
dimension "flavor"
|
||||
applicationIdSuffix ".fdroid"
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
|
@ -28,8 +28,15 @@
|
||||
<intent-filter>
|
||||
<action
|
||||
android:name="com.android_package_installer.content.SESSION_API_PACKAGE_INSTALLED"
|
||||
android:exported="false"/>
|
||||
android:exported="false" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="obtainium" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
@ -39,10 +46,10 @@
|
||||
<service
|
||||
android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="false"/>
|
||||
android:exported="false" />
|
||||
<receiver
|
||||
android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmBroadcastReceiver"
|
||||
android:exported="false"/>
|
||||
android:exported="false" />
|
||||
<receiver
|
||||
android:name="dev.fluttercommunity.plus.androidalarmmanager.RebootBroadcastReceiver"
|
||||
android:enabled="false"
|
||||
@ -52,24 +59,24 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="dev.imranr.obtainium"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths"/>
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="dev.imranr.obtainium"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29"/>
|
||||
android:maxSdkVersion="29" />
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||
</manifest>
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Nije instalirano",
|
||||
"estimateInBrackets": "(Procjena)",
|
||||
"selectAll": "Označi sve",
|
||||
"deselectN": "Poništi odabir {}",
|
||||
"deselectX": "Poništi odabir {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} će biti uklonjen iz Obtainiuma, ali će ostati instaliran na uređaju.",
|
||||
"removeSelectedAppsQuestion": "Želite li ukloniti odabrane aplikacije?",
|
||||
"removeSelectedApps": "Ukloni odabrane aplikacije",
|
||||
@ -88,7 +88,7 @@
|
||||
"importExport": "Uvoz/izvoz",
|
||||
"settings": "Postavke",
|
||||
"exportedTo": "Izvezeno u {}",
|
||||
"obtainiumExport": "Obtainium Export",
|
||||
"obtainiumExport": "Obtainium izvoz",
|
||||
"invalidInput": "Neispravan unos.",
|
||||
"importedX": "Uvezeno {}",
|
||||
"obtainiumImport": "Obtainium uvoz",
|
||||
@ -134,7 +134,7 @@
|
||||
"close": "Zatvori",
|
||||
"share": "Podijeli",
|
||||
"appNotFound": "Aplikacija nije pronađena",
|
||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||
"obtainiumExportHyphenatedLowercase": "obtainium-izvoz",
|
||||
"pickAnAPK": "Odaberite APK",
|
||||
"appHasMoreThanOnePackage": "{} ima više od jednog paketa:",
|
||||
"deviceSupportsXArch": "Vaš uređaj podržava {} arhitekturu procesora.",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "Premjesti neinstalirane aplikacije na dno prikaza aplikacija",
|
||||
"gitlabPATLabel": "GitLab token za lični pristup\n(Omogućava pretraživanje i bolje otkrivanje APK-a)",
|
||||
"about": "O nama",
|
||||
"requiresCredentialsInSettings": "Za ovo su potrebni dodatni akreditivi (u Postavkama)",
|
||||
"requiresCredentialsInSettings": "{}: Za ovo su potrebni dodatni akreditivi (u Postavkama)",
|
||||
"checkOnStart": "Provjerite ima li novosti pri pokretanju",
|
||||
"tryInferAppIdFromCode": "Pokušati otkriti ID aplikacije iz izvornog koda",
|
||||
"removeOnExternalUninstall": "Automatski ukloni eksterno deinstalirane aplikacije",
|
||||
@ -231,49 +231,53 @@
|
||||
"checkUpdateOnDetailPage": "Provjerite ima li novosti pri otvaranju stranice s detaljima aplikacije",
|
||||
"disablePageTransitions": "Ugasite animaciju prijelaza stranice",
|
||||
"reversePageTransitions": "Reverzne animacije prijelaza stranice",
|
||||
"minStarCount": "Minimum Star Count",
|
||||
"addInfoBelow": "Add this info below.",
|
||||
"addInfoInSettings": "Add this info in the Settings.",
|
||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
||||
"appsPossiblyUpdated": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
|
||||
"xWasPossiblyUpdatedToY": "{} may have been updated to {}.",
|
||||
"enableBackgroundUpdates": "Enable background updates",
|
||||
"backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.",
|
||||
"backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.",
|
||||
"verifyLatestTag": "Verify the 'latest' tag",
|
||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First",
|
||||
"intermediateLinkNotFound": "Intermediate link not found",
|
||||
"exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)",
|
||||
"bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
|
||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
||||
"matchGroupToUse": "Match Group to Use",
|
||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||
"pickExportDir": "Pick Export Directory",
|
||||
"autoExportOnChanges": "Auto-export on changes",
|
||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
"reverseSort": "Reverse sorting",
|
||||
"debugMenu": "Debug Menu",
|
||||
"bgTaskStarted": "Background task started - check logs.",
|
||||
"runBgCheckNow": "Run Background Update Check Now",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"minStarCount": "Najmanji broj zvjezdica",
|
||||
"addInfoBelow": "Dodajte ove informacije ispod.",
|
||||
"addInfoInSettings": "Dodajte ove informacije u Postavkama.",
|
||||
"githubSourceNote": "GitHub ograničavanje se može izbjeći korišćenjem tokena za lični pristup.",
|
||||
"gitlabSourceNote": "GitLab APK preuzimanje možda neće raditi bez tokena za lični pristup.",
|
||||
"sortByFileNamesNotLinks": "Sortirajte po imenima datoteka umjesto po punim linkovima",
|
||||
"filterReleaseNotesByRegEx": "Filtirajte promjene u izdanju po regularnom izrazu",
|
||||
"customLinkFilterRegex": "Prilagođeni APK link filtrira se po regularnom izrazu (Zadano '.apk$')",
|
||||
"appsPossiblyUpdated": "Pokušano ažuriranje aplikacija",
|
||||
"appsPossiblyUpdatedNotifDescription": "Obavještava korisnika da je ažuriranje jedne ili više aplikacija potencijalno izvršeno u pozadini",
|
||||
"xWasPossiblyUpdatedToY": "{} aplikacija bi trebala biti ažurirana na {}.",
|
||||
"enableBackgroundUpdates": "Dozvolite ažuriranja u pozadini",
|
||||
"backgroundUpdateReqsExplanation": "Ažuriranja u pozadini možda neće raditi za sve aplikacije.",
|
||||
"backgroundUpdateLimitsExplanation": "Uspjeh ažuriranja u pozadini se može provjeriti tek kada otvorite Obtainium.",
|
||||
"verifyLatestTag": "Provjerite 'posljednu' ('latest') oznaku",
|
||||
"intermediateLinkRegex": "Filtrirajte da prvo posjetite 'Intemediate' link",
|
||||
"intermediateLinkNotFound": "Intermediate link nije nađen",
|
||||
"exemptFromBackgroundUpdates": "Izuzmi iz ažuriranja u pozadini (ako su uključeni)",
|
||||
"bgUpdatesOnWiFiOnly": "Isključite ažuriranje u pozadini kada niste na WiFi-ju",
|
||||
"autoSelectHighestVersionCode": "Automatski izaberite najveću (verziju) versionCode APK-a",
|
||||
"versionExtractionRegEx": "RegEx ekstrakcija verzije",
|
||||
"matchGroupToUse": "Podjesite grupu za upotebu",
|
||||
"highlightTouchTargets": "Istaknite manje vidljive touch mete",
|
||||
"pickExportDir": "Izaberite datoteku za izvoz",
|
||||
"autoExportOnChanges": "Automatski izvezite pri promjenama",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filtrirajte verzije po regulatnom izrazu",
|
||||
"trySelectingSuggestedVersionCode": "Probajte izabrati preloženu (verziju) versionCode APK-a",
|
||||
"dontSortReleasesList": "Zadrži redosled izdanja iz API-a",
|
||||
"reverseSort": "Obrni redosled",
|
||||
"debugMenu": "Meni za otkrivanje grešaka",
|
||||
"bgTaskStarted": "Rad u pozadini pokrenut - provjerite log-ove.",
|
||||
"runBgCheckNow": "Pokrenite pozadinsku provjeru ažuriranja sad",
|
||||
"versionExtractWholePage": "Primjenite Regex ekstrakciju verzije na cijelu stranicu",
|
||||
"installing": "Instaliranje",
|
||||
"skipUpdateNotifications": "Ne prikazujte obavještenja ažuriranja",
|
||||
"updatesAvailableNotifChannel": "Dostupna ažuriranja",
|
||||
"appsUpdatedNotifChannel": "Aplikacije su ažurirane",
|
||||
"appsPossiblyUpdatedNotifChannel": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifChannel": "Pokušano ažuriranje aplikacija",
|
||||
"errorCheckingUpdatesNotifChannel": "Greška pri provjeri ažuriranja",
|
||||
"appsRemovedNotifChannel": "Aplikacije su uklonjene",
|
||||
"downloadingXNotifChannel": "Preuzimanje {}",
|
||||
"completeAppInstallationNotifChannel": "Dovršite instalaciju aplikacije",
|
||||
"checkingForUpdatesNotifChannel": "Tražim moguće nadogradnje",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Isključivo provjerite ažuriranje za instalirane i aplikacije 'samo za praćenje'",
|
||||
"supportFixedAPKURL": "Podržite fiksne APK URL-ove",
|
||||
"selectX": "Izaberite {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Želite li ukloniti aplikaciju?",
|
||||
"other": "Želite li ukloniti aplikacije?"
|
||||
@ -323,7 +327,7 @@
|
||||
"other": "{} i još {} aplikacija je ažurirano."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} and 1 more app may have been updated.",
|
||||
"other": "{} and {} more apps may have been updated."
|
||||
"one": "{} i još jedna aplikacija je vjerovatno ažurirana.",
|
||||
"other": "{} i još {} aplikacija su vjerovatno ažurirane."
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Není nainstalováno",
|
||||
"estimateInBrackets": "(přibližně)",
|
||||
"selectAll": "Vybrat Vše",
|
||||
"deselectN": "{} deselected",
|
||||
"deselectX": "{} deselected",
|
||||
"xWillBeRemovedButRemainInstalled": "{} bude odstraněn z Obtainium, ale zůstane nainstalován v zařízení.",
|
||||
"removeSelectedAppsQuestion": "Odebrat vybrané aplikace?",
|
||||
"removeSelectedApps": "Odebrat vybrané aplikace",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "Přesunout nenainstalované aplikace na konec zobrazení Aplikace",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Umožňuje vyhledávání a lepší zjišťování APK)",
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "Vyžaduje další pověření (v nastavení)",
|
||||
"requiresCredentialsInSettings": "{}: Vyžaduje další pověření (v nastavení)",
|
||||
"checkOnStart": "Zkontrolovat jednou při spuštění",
|
||||
"tryInferAppIdFromCode": "Pokusit se určit ID aplikace ze zdrojového kódu",
|
||||
"removeOnExternalUninstall": "Automaticky odstranit externě odinstalované aplikace",
|
||||
@ -256,6 +256,7 @@
|
||||
"highlightTouchTargets": "Zvýraznit méně zjevné cíle dotyku",
|
||||
"pickExportDir": "Vybrat adresář pro export",
|
||||
"autoExportOnChanges": "Automatický export při změnách",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filtrovat verze podle regulárního výrazu",
|
||||
"trySelectingSuggestedVersionCode": "Zkusit vybrat navrhovaný kód verze APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "download {}",
|
||||
"completeAppInstallationNotifChannel": "Dokončit instalaci aplikace",
|
||||
"checkingForUpdatesNotifChannel": "Zkontrolovat aktualizace",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Odstranit Apku?",
|
||||
"other": "Odstranit Apky?"
|
||||
|
@ -24,7 +24,7 @@
|
||||
"colour": "Farbe",
|
||||
"githubStarredRepos": "GitHub Starred Repos",
|
||||
"uname": "Benutzername",
|
||||
"wrongArgNum": "Falsche Anzahl von Argumenten übermittelt",
|
||||
"wrongArgNum": "Falsche Anzahl von Argumenten (Parametern) übermittelt",
|
||||
"xIsTrackOnly": "{} ist nur zur Nachverfolgung",
|
||||
"source": "Quelle",
|
||||
"app": "App",
|
||||
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Nicht installiert",
|
||||
"estimateInBrackets": "(Ungefähr)",
|
||||
"selectAll": "Alle auswählen",
|
||||
"deselectN": "{} abgewählt",
|
||||
"deselectX": "{} abgewählt",
|
||||
"xWillBeRemovedButRemainInstalled": "{} wird aus Obtainium entfernt, bleibt aber auf dem Gerät installiert.",
|
||||
"removeSelectedAppsQuestion": "Ausgewählte Apps entfernen?",
|
||||
"removeSelectedApps": "Ausgewählte Apps entfernen",
|
||||
@ -76,7 +76,7 @@
|
||||
"shareSelectedAppURLs": "Ausgewählte App-URLs teilen",
|
||||
"resetInstallStatus": "Installationsstatus zurücksetzen",
|
||||
"more": "Mehr",
|
||||
"removeOutdatedFilter": "App-Filter 'Nicht aktuell' entfernen",
|
||||
"removeOutdatedFilter": "App-Filter ‚Nicht aktuell‘ entfernen",
|
||||
"showOutdatedOnly": "Nur nicht aktuelle Apps anzeigen",
|
||||
"filter": "Filter",
|
||||
"filterActive": "Filter *",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Aktiviert Suche und bessere APK Entdeckung)",
|
||||
"about": "Über",
|
||||
"requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)",
|
||||
"requiresCredentialsInSettings": "{}: Benötigt zusätzliche Anmeldedaten (in den Einstellungen)",
|
||||
"checkOnStart": "Überprüfe einmalig beim Start",
|
||||
"tryInferAppIdFromCode": "Versuche, die App-ID aus dem Quellcode zu ermitteln",
|
||||
"removeOnExternalUninstall": "Automatisches Entfernen von extern deinstallierten Apps",
|
||||
@ -250,14 +250,15 @@
|
||||
"intermediateLinkNotFound": "„Zwischen“link nicht gefunden",
|
||||
"exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)",
|
||||
"bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist",
|
||||
"autoSelectHighestVersionCode": "Automatisch höchste APK-Code-Version auswählen",
|
||||
"autoSelectHighestVersionCode": "Automatisch höchste APK-Version auswählen",
|
||||
"versionExtractionRegEx": "Versions-Extraktion per RegEx",
|
||||
"matchGroupToUse": "Zu verwendende Gruppe abgleichen",
|
||||
"highlightTouchTargets": "Weniger offensichtliche Ziele hervorheben",
|
||||
"matchGroupToUse": "zu verwendende Gruppe abgleichen",
|
||||
"highlightTouchTargets": "Weniger offensichtliche Touch-Ziele hervorheben",
|
||||
"pickExportDir": "Export-Verzeichnis wählen",
|
||||
"autoExportOnChanges": "Automatischer Export bei Änderung",
|
||||
"autoExportOnChanges": "Automatischer Export bei Änderung(en)",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Versionen nach regulären Ausdrücken filtern",
|
||||
"trySelectingSuggestedVersionCode": "Versuchen, die vorgeschlagene APK-Code-Version auszuwählen",
|
||||
"trySelectingSuggestedVersionCode": "Versuchen, den vorgeschlagenen APK-Versionscode auszuwählen",
|
||||
"dontSortReleasesList": "Freigaberelease von der API ordern",
|
||||
"reverseSort": "Umgekehrtes Sortieren",
|
||||
"debugMenu": "Debug-Menü",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "Lade {} herunter",
|
||||
"completeAppInstallationNotifChannel": "App Installation abschließen",
|
||||
"checkingForUpdatesNotifChannel": "Nach Aktualisierungen suchen",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Überprüfe nur installierte und mit „nur Nachverfolgen“ markierte Apps auf Aktualisierungen",
|
||||
"supportFixedAPKURL": "neuere Version anhand der ersten dreißig Zahlen der Checksumme der APK URL erraten, wenn anderweitig nicht unterstützt",
|
||||
"selectX": "Wähle {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "App entfernen?",
|
||||
"other": "Apps entfernen?"
|
||||
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Not Installed",
|
||||
"estimateInBrackets": "(Estimate)",
|
||||
"selectAll": "Select All",
|
||||
"deselectN": "Deselect {}",
|
||||
"deselectX": "Deselect {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.",
|
||||
"removeSelectedAppsQuestion": "Remove Selected Apps?",
|
||||
"removeSelectedApps": "Remove Selected Apps",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)",
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"requiresCredentialsInSettings": "{} needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check for updates on startup",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
||||
@ -256,6 +256,7 @@
|
||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||
"pickExportDir": "Pick Export Directory",
|
||||
"autoExportOnChanges": "Auto-export on changes",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "Downloading {}",
|
||||
"completeAppInstallationNotifChannel": "Complete App Installation",
|
||||
"checkingForUpdatesNotifChannel": "Checking for Updates",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Remove App?",
|
||||
"other": "Remove Apps?"
|
||||
|
@ -14,8 +14,8 @@
|
||||
"githubPATLabel": "Token de Acceso Personal de GitHub (Reduce tiempos de espera)",
|
||||
"includePrereleases": "Incluir versiones preliminares",
|
||||
"fallbackToOlderReleases": "Retorceder a versiones previas",
|
||||
"filterReleaseTitlesByRegEx": "Filtra Títulos de Versiones mediantes Expresiones Regulares",
|
||||
"invalidRegEx": "Expresión regular inválida",
|
||||
"filterReleaseTitlesByRegEx": "Filtrar Títulos de Versiones",
|
||||
"invalidRegEx": "Expresión inválida",
|
||||
"noDescription": "Sin descripción",
|
||||
"cancel": "Cancelar",
|
||||
"continue": "Continuar",
|
||||
@ -30,7 +30,7 @@
|
||||
"app": "Aplicación",
|
||||
"appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'Solo Seguimiento'.",
|
||||
"youPickedTrackOnly": "Debes seleccionar la opción de 'Solo Seguimiento'.",
|
||||
"trackOnlyAppDescription": "Se monitorizará la aplicación en busca de actualizaciones, pero Obtainium no será capaz de descargarla o acutalizarla.",
|
||||
"trackOnlyAppDescription": "Se monitorizará la aplicación en busca de actualizaciones, pero Obtainium no será capaz de descargarla o actalizarla.",
|
||||
"cancelled": "Cancelado",
|
||||
"appAlreadyAdded": "Aplicación ya añadida",
|
||||
"alreadyUpToDateQuestion": "¿Aplicación ya actualizada?",
|
||||
@ -55,13 +55,13 @@
|
||||
"notInstalled": "No Instalado",
|
||||
"estimateInBrackets": "(Aproximado)",
|
||||
"selectAll": "Seleccionar Todo",
|
||||
"deselectN": "Deseleccionar {}",
|
||||
"deselectX": "Deseleccionar {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} será borrada de Obtainium pero continuará instalada en el dispositivo.",
|
||||
"removeSelectedAppsQuestion": "¿Borrar aplicaciones seleccionadas?",
|
||||
"removeSelectedApps": "Borrar Aplicaciones Seleccionadas",
|
||||
"updateX": "Actualizar {}",
|
||||
"installX": "Instalar {}",
|
||||
"markXTrackOnlyAsUpdated": "Marcar {}\n(Solo Seguimient)\ncomo Actualizada",
|
||||
"markXTrackOnlyAsUpdated": "Marcar {}\n(Solo Seguimiento)\ncomo Actualizada",
|
||||
"changeX": "Cambiar {}",
|
||||
"installUpdateApps": "Instalar/Actualizar Aplicaciones",
|
||||
"installUpdateSelectedApps": "Instalar/Actualizar Aplicaciones Seleccionadas",
|
||||
@ -72,7 +72,7 @@
|
||||
"pinToTop": "Fijar arriba",
|
||||
"unpinFromTop": "Desfijar de arriba",
|
||||
"resetInstallStatusForSelectedAppsQuestion": "¿Restuarar Estado de Instalación para las Aplicaciones Seleccionadas?",
|
||||
"installStatusOfXWillBeResetExplanation": "El estado de instalación de las aplicaciones seleccionadas será restaurado.\n\nEsto puede ser de utilidad cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.",
|
||||
"installStatusOfXWillBeResetExplanation": "El estado de instalación de las aplicaciones seleccionadas será restaurado.\n\nEsto puede ser de útil cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.",
|
||||
"shareSelectedAppURLs": "Compartir URLs de las Aplicaciones Seleccionadas",
|
||||
"resetInstallStatus": "Restaurar Estado de Instalación",
|
||||
"more": "Más",
|
||||
@ -100,7 +100,7 @@
|
||||
"noResults": "Resultados no encontrados",
|
||||
"importX": "Importar {}",
|
||||
"importedAppsIdDisclaimer": "Las Aplicaciones Importadas pueden mostrarse incorrectamente como \"No Instalada\".\nPara arreglar esto, reinstálalas a través de Obtainium.\nEsto no debería afectar a los datos de las aplicaciones.\n\nSolo afecta a las URLs y a los métodos de importación mediante terceros.",
|
||||
"importErrors": "Import Errors",
|
||||
"importErrors": "Errores de Importación",
|
||||
"importedXOfYApps": "{} de {} Aplicaciones importadas.",
|
||||
"followingURLsHadErrors": "Las siguientes URLs tuvieron problemas:",
|
||||
"okay": "Correcto",
|
||||
@ -135,7 +135,7 @@
|
||||
"share": "Compartir",
|
||||
"appNotFound": "Aplicación no encontrada",
|
||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||
"pickAnAPK": "Elige una APK",
|
||||
"pickAnAPK": "Selecciona una APK",
|
||||
"appHasMoreThanOnePackage": "{} tiene más de un paquete:",
|
||||
"deviceSupportsXArch": "Tu dispositivo soporta las siguientes arquitecturas de procesador: {}.",
|
||||
"deviceSupportsFollowingArchs": "Tu dispositivo soporta las siguientes arquitecturas de procesador:",
|
||||
@ -154,8 +154,8 @@
|
||||
"appsRemovedNotifDescription": "Notifica al usuario que una o más aplicaciones fueron eliminadas por problemas al cargarlas",
|
||||
"xWasRemovedDueToErrorY": "{} ha sido eliminada por: {}",
|
||||
"completeAppInstallation": "Instalación Completa de la Aplicación",
|
||||
"obtainiumMustBeOpenToInstallApps": "Obtainium debe estar abierta para instalar aplicaciones",
|
||||
"completeAppInstallationNotifDescription": "Pide al usuario volver a Obtainium para teminar de instalar una aplicación",
|
||||
"obtainiumMustBeOpenToInstallApps": "Obtainium debe estar abierto para instalar aplicaciones",
|
||||
"completeAppInstallationNotifDescription": "Pide al usuario volver a Obtainium para terminar de instalar una aplicación",
|
||||
"checkingForUpdates": "Buscando Actualizaciones",
|
||||
"checkingForUpdatesNotifDescription": "Notificación temporal que aparece al buscar actualizaciones",
|
||||
"pleaseAllowInstallPerm": "Por favor, permite a Obtainium instalar aplicaciones",
|
||||
@ -180,14 +180,14 @@
|
||||
"steamMobile": "Steam Mobile",
|
||||
"steamChat": "Steam Chat",
|
||||
"install": "Instalar",
|
||||
"markInstalled": "Marcar como Instalda",
|
||||
"markInstalled": "Marcar como Instalada",
|
||||
"update": "Actualizar",
|
||||
"markUpdated": "Marcar como Actualizada",
|
||||
"additionalOptions": "Opciones Adicionales",
|
||||
"disableVersionDetection": "Descativar Detección de Versiones",
|
||||
"noVersionDetectionExplanation": "Esta opción solo se debe usar en aplicaciones en las que la deteción de versiones pueda no funcionar correctamente.",
|
||||
"downloadingX": "Descargando {}",
|
||||
"downloadNotifDescription": "Notifica al usuario de progreso de descarga de una aplicación",
|
||||
"downloadNotifDescription": "Notifica al usuario del progreso de descarga de una aplicación",
|
||||
"noAPKFound": "APK no encontrada",
|
||||
"noVersionDetection": "Sin detección de versiones",
|
||||
"categorize": "Catogorizar",
|
||||
@ -196,14 +196,14 @@
|
||||
"noCategory": "Sin Categoría",
|
||||
"noCategories": "Sin Categorías",
|
||||
"deleteCategoriesQuestion": "¿Borrar Categorías?",
|
||||
"categoryDeleteWarning": "Todas las aplicaciones en las categorías borradas serán margadas como 'Sin Categoría'.",
|
||||
"categoryDeleteWarning": "Todas las aplicaciones en las categorías borradas serán marcadas como 'Sin Categoría'.",
|
||||
"addCategory": "Añadir Categoría",
|
||||
"label": "Nombre",
|
||||
"language": "Idioma",
|
||||
"copiedToClipboard": "Copiado al Portapapeles",
|
||||
"storagePermissionDenied": "Permiso de Almacenamiento rechazado",
|
||||
"selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaicones seleccionadas.",
|
||||
"filterAPKsByRegEx": "Filtrar APKs mediante Expresiones Regulares",
|
||||
"selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaciones seleccionadas.",
|
||||
"filterAPKsByRegEx": "Filtrar por APKs",
|
||||
"removeFromObtainium": "Eliminar de Obtainium",
|
||||
"uninstallFromDevice": "Desinstalar del Dispositivo",
|
||||
"onlyWorksWithNonVersionDetectApps": "Solo funciona para aplicaciones con la detección de versiones desactivada.",
|
||||
@ -211,69 +211,73 @@
|
||||
"releaseDateAsVersionExplanation": "Esta opción solo se debería usar con aplicaciones en las que la detección de versiones no funciona pero hay disponible una fecha de publicación.",
|
||||
"changes": "Cambios",
|
||||
"releaseDate": "Fecha de Publicación",
|
||||
"importFromURLsInFile": "Importar de URls en un Archivo (como OPML)",
|
||||
"importFromURLsInFile": "Importar de URls desde un Archivo (como OPML)",
|
||||
"versionDetection": "Detección de Versiones",
|
||||
"standardVersionDetection": "Detección de versiones estándar",
|
||||
"groupByCategory": "Agrupar por Categoría",
|
||||
"autoApkFilterByArch": "Tratar de filtrar las APKs mediante arquitecturas de procesador si es posible",
|
||||
"autoApkFilterByArch": "Filtrar las APKs mediante arquitecturas de procesador, si es posible",
|
||||
"overrideSource": "Sobrescribir Fuente",
|
||||
"dontShowAgain": "No mostrar de nuevo",
|
||||
"dontShowTrackOnlyWarnings": "No mostrar avisos de 'Solo Seguimiento'",
|
||||
"dontShowAPKOriginWarnings": "No mostrar avisos de las fuentes de las APks",
|
||||
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)",
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check for updates on startup",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
||||
"pickHighestVersionCode": "Auto-select highest version code APK",
|
||||
"checkUpdateOnDetailPage": "Check for updates on opening an App detail page",
|
||||
"disablePageTransitions": "Disable page transition animations",
|
||||
"reversePageTransitions": "Reverse page transition animations",
|
||||
"minStarCount": "Minimum Star Count",
|
||||
"addInfoBelow": "Add this info below.",
|
||||
"addInfoInSettings": "Add this info in the Settings.",
|
||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
||||
"appsPossiblyUpdated": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
|
||||
"xWasPossiblyUpdatedToY": "{} may have been updated to {}.",
|
||||
"enableBackgroundUpdates": "Enable background updates",
|
||||
"backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.",
|
||||
"backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.",
|
||||
"verifyLatestTag": "Verify the 'latest' tag",
|
||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First",
|
||||
"intermediateLinkNotFound": "Intermediate link not found",
|
||||
"exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)",
|
||||
"bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
|
||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
||||
"moveNonInstalledAppsToBottom": "Mover las Apps no instaladas al final de la vista de Apps",
|
||||
"gitlabPATLabel": "Token GitLab de Acceso Personal\n(Habilita la Búsqueda y Mejor Detección de APKs)",
|
||||
"about": "Acerca",
|
||||
"requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en Ajustes)",
|
||||
"checkOnStart": "Comprobar actualizaciones durante el inicio",
|
||||
"tryInferAppIdFromCode": "Intentar deducir la ID de la APP por el código fuente",
|
||||
"removeOnExternalUninstall": "Auto eliminar Apps desinstaladas externamente",
|
||||
"pickHighestVersionCode": "Auto selección versión superior del código APK",
|
||||
"checkUpdateOnDetailPage": "Comprobar actualizaciones al abrir detalles de la App",
|
||||
"disablePageTransitions": "Deshabilitar animaciones de transición de la página",
|
||||
"reversePageTransitions": "Invertir las animaciones de transición de la página",
|
||||
"minStarCount": "Número Mínimo de Estrellas",
|
||||
"addInfoBelow": "Añadir esta información debajo.",
|
||||
"addInfoInSettings": "Añadir esta información en Ajustes.",
|
||||
"githubSourceNote": "La limitación de velocidad de GitHub puede evitarse con una clave API.",
|
||||
"gitlabSourceNote": "La extracción de APK de GitLab podría no funcionar sin una clave API.",
|
||||
"sortByFileNamesNotLinks": "Ordenar por nombres de fichero en vez de por enlaces completos",
|
||||
"filterReleaseNotesByRegEx": "Filtrar por Notas de Versión (Release Notes)",
|
||||
"customLinkFilterRegex": "Filtro personalizado de Enlace APK (por defecto '.apk$')",
|
||||
"appsPossiblyUpdated": "Actualización de Apps intentada",
|
||||
"appsPossiblyUpdatedNotifDescription": "Notifica al usuario que las actualizaciones en segundo plano podrían haberse realizado para una o más aplicaciones",
|
||||
"xWasPossiblyUpdatedToY": "{} podría estar actualizada a {}.",
|
||||
"enableBackgroundUpdates": "Habilitar actualizaciones en segundo plano",
|
||||
"backgroundUpdateReqsExplanation": "Las actualizaciones en segundo plano pueden no estar disponibles para todas las aplicaciones.",
|
||||
"backgroundUpdateLimitsExplanation": "El éxito de las instalaciones en segundo plano solo se puede verificar con Obtainium abierto.",
|
||||
"verifyLatestTag": "Verifica la etiqueta 'latest'",
|
||||
"intermediateLinkRegex": "Filtrar por Enlace 'Intermedio' para Visitar Primero",
|
||||
"intermediateLinkNotFound": "Enlace Intermedio no encontrado",
|
||||
"exemptFromBackgroundUpdates": "Exento de actualizciones en segundo plano (si están habilitadas)",
|
||||
"bgUpdatesOnWiFiOnly": "Deshabilitar las actualizaciones en segundo plano sin WiFi",
|
||||
"autoSelectHighestVersionCode": "Auto Selección de la versionCode APK superior",
|
||||
"versionExtractionRegEx": "Versión de Extracción de RegEx",
|
||||
"matchGroupToUse": "Match Group to Use",
|
||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||
"pickExportDir": "Pick Export Directory",
|
||||
"autoExportOnChanges": "Auto-export on changes",
|
||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
"reverseSort": "Reverse sorting",
|
||||
"debugMenu": "Debug Menu",
|
||||
"bgTaskStarted": "Background task started - check logs.",
|
||||
"runBgCheckNow": "Run Background Update Check Now",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"highlightTouchTargets": "Resaltar objetivos menos obvios",
|
||||
"pickExportDir": "Selecciona el Directorio para Exportar",
|
||||
"autoExportOnChanges": "Auto Exportar cuando haya cambios",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filtrar por Versiones",
|
||||
"trySelectingSuggestedVersionCode": "Prueba seleccionando la versionCode APK sugerida",
|
||||
"dontSortReleasesList": "Mantener el order de publicación desde API",
|
||||
"reverseSort": "Orden inverso",
|
||||
"debugMenu": "Menu Depurar",
|
||||
"bgTaskStarted": "Iniciada tarea en segundo plano - revisa los logs.",
|
||||
"runBgCheckNow": "Ejecutar verficiación de actualizaciones en segundo plano",
|
||||
"versionExtractWholePage": "Aplicar la Versión de Extracción Regex a la Página Entera",
|
||||
"installing": "Instalando",
|
||||
"skipUpdateNotifications": "Omitir notificaciones sobre actualizaciones",
|
||||
"updatesAvailableNotifChannel": "Actualizaciones Disponibles",
|
||||
"appsUpdatedNotifChannel": "Aplicaciones Actualizadas",
|
||||
"appsPossiblyUpdatedNotifChannel": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifChannel": "Se ha Intentado Actualizar la Aplicación",
|
||||
"errorCheckingUpdatesNotifChannel": "Error Buscando Actualizaciones",
|
||||
"appsRemovedNotifChannel": "Aplicaciones Eliminadas",
|
||||
"downloadingXNotifChannel": "Descargando {}",
|
||||
"completeAppInstallationNotifChannel": "Instalación Completa de la Aplicación",
|
||||
"checkingForUpdatesNotifChannel": "Buscando Actualizaciones",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates",
|
||||
"supportFixedAPKURL": "Soporte para URLs fijas de APK",
|
||||
"selectX": "Selecciona {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "¿Eliminar Aplicación?",
|
||||
"other": "¿Eliminar Aplicaciones?"
|
||||
@ -316,14 +320,14 @@
|
||||
},
|
||||
"xAndNMoreUpdatesAvailable": {
|
||||
"one": "{} y 1 aplicación más tiene actualizaciones.",
|
||||
"other": "{} y {} aplicaciones más tiene actualizaciones."
|
||||
"other": "{} y {} aplicaciones más tienen actualizaciones."
|
||||
},
|
||||
"xAndNMoreUpdatesInstalled": {
|
||||
"one": "{} y 1 aplicación más han sido actualizadas.",
|
||||
"other": "{} y {} aplicaciones más han sido actualizadas."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} and 1 more app may have been updated.",
|
||||
"other": "{} and {} more apps may have been updated."
|
||||
"one": "{} y 1 aplicación más podría haber sido actualizada.",
|
||||
"other": "{} y {} aplicaciones más podrían haber sido actualizadas."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "نصب نشده",
|
||||
"estimateInBrackets": "(تخمین زدن)",
|
||||
"selectAll": "انتخاب همه",
|
||||
"deselectN": "لغو انتخاب {}",
|
||||
"deselectX": "لغو انتخاب {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} از Obtainium حذف میشود اما روی دستگاه نصب میماند.",
|
||||
"removeSelectedAppsQuestion": "برنامه های انتخابی حذف شود؟",
|
||||
"removeSelectedApps": "حذف برنامه های انتخاب شده",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید",
|
||||
"gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو و کشف بهتر APK را فعال میکند)",
|
||||
"about": "درباره",
|
||||
"requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)",
|
||||
"requiresCredentialsInSettings": "{}: این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)",
|
||||
"checkOnStart": "بررسی در شروع",
|
||||
"tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید",
|
||||
"removeOnExternalUninstall": "حذف خودکار برنامه های حذف نصب شده خارجی",
|
||||
@ -239,41 +239,45 @@
|
||||
"sortByFileNamesNotLinks": "مرتب سازی بر اساس نام فایل به جای پیوندهای کامل",
|
||||
"filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید",
|
||||
"customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیشفرض '.apk$')",
|
||||
"appsPossiblyUpdated": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
|
||||
"xWasPossiblyUpdatedToY": "{} may have been updated to {}.",
|
||||
"enableBackgroundUpdates": "Enable background updates",
|
||||
"backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.",
|
||||
"backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.",
|
||||
"verifyLatestTag": "Verify the 'latest' tag",
|
||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First",
|
||||
"intermediateLinkNotFound": "Intermediate link not found",
|
||||
"exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)",
|
||||
"bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
|
||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
||||
"matchGroupToUse": "Match Group to Use",
|
||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||
"pickExportDir": "Pick Export Directory",
|
||||
"autoExportOnChanges": "Auto-export on changes",
|
||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
"reverseSort": "Reverse sorting",
|
||||
"debugMenu": "Debug Menu",
|
||||
"bgTaskStarted": "Background task started - check logs.",
|
||||
"runBgCheckNow": "Run Background Update Check Now",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"appsPossiblyUpdated": "بهروزرسانی برنامه انجام شد",
|
||||
"appsPossiblyUpdatedNotifDescription": "به کاربر اطلاع میدهد که بهروزرسانیهای یک یا چند برنامه به طور بالقوه در پسزمینه اعمال شده است",
|
||||
"xWasPossiblyUpdatedToY": "ممکن است {} به {} به روز شده باشد.",
|
||||
"enableBackgroundUpdates": "به روز رسانی پس زمینه را فعال کنید",
|
||||
"backgroundUpdateReqsExplanation": "به روز رسانی پس زمینه ممکن است برای همه برنامه ها امکان پذیر نباشد.",
|
||||
"backgroundUpdateLimitsExplanation": "موفقیت نصب پسزمینه تنها زمانی مشخص میشود که Obtainium باز شود.",
|
||||
"verifyLatestTag": "برچسب "آخرین" را تأیید کنید",
|
||||
"intermediateLinkRegex": "برای اولین بار بازدید از لینک "متوسط" را فیلتر کنید",
|
||||
"intermediateLinkNotFound": "لینک میانی پیدا نشد",
|
||||
"exemptFromBackgroundUpdates": "معاف از بهروزرسانیهای پسزمینه (در صورت فعال بودن)",
|
||||
"bgUpdatesOnWiFiOnly": "بهروزرسانیهای پسزمینه را در صورت عدم اتصال به WiFi غیرفعال کنید",
|
||||
"autoSelectHighestVersionCode": "انتخاب خودکار بالاترین نسخه کد APK",
|
||||
"versionExtractionRegEx": "نسخه استخراج RegEx",
|
||||
"matchGroupToUse": "گروه مورد استفاده را مطابقت دهید",
|
||||
"highlightTouchTargets": "اهداف لمسی کمتر واضح را برجسته کنید",
|
||||
"pickExportDir": "فهرست صادرات را انتخاب کنید",
|
||||
"autoExportOnChanges": "صادرات خودکار تغییرات",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "فیلتر کردن نسخه ها با RegEx",
|
||||
"trySelectingSuggestedVersionCode": "نسخه پیشنهادی APK نسخه کد را انتخاب کنید",
|
||||
"dontSortReleasesList": "حفظ سفارش انتشار از API",
|
||||
"reverseSort": "مرتب سازی معکوس",
|
||||
"debugMenu": "منوی اشکال زدایی",
|
||||
"bgTaskStarted": "کار پس زمینه شروع شد - لاگ های مربوط را بررسی کنید.",
|
||||
"runBgCheckNow": "اکنون بهروزرسانی پسزمینه را بررسی کنید",
|
||||
"versionExtractWholePage": "نسخه Extraction Regex را در کل صفحه اعمال کنید",
|
||||
"installing": "در حال نصب",
|
||||
"skipUpdateNotifications": "رد شدن از اعلان های به روز رسانی",
|
||||
"updatesAvailableNotifChannel": "بروزرسانی در دسترس ",
|
||||
"appsUpdatedNotifChannel": "برنامه ها به روز شدند",
|
||||
"appsPossiblyUpdatedNotifChannel": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifChannel": "بهروزرسانی برنامه انجام شد",
|
||||
"errorCheckingUpdatesNotifChannel": "خطا در بررسی بهروزرسانیها",
|
||||
"appsRemovedNotifChannel": "برنامه ها حذف شدند",
|
||||
"downloadingXNotifChannel": "در حال دانلود {}",
|
||||
"completeAppInstallationNotifChannel": "نصب کامل برنامه",
|
||||
"checkingForUpdatesNotifChannel": "بررسی بهروزرسانیها",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "فقط برنامه های نصب شده و فقط ردیابی را برای به روز رسانی بررسی کنید",
|
||||
"supportFixedAPKURL": "پشتیبانی از URL های APK ثابت",
|
||||
"selectX": "انتخاب کنید {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "برنامه حذف شود؟",
|
||||
"other": "برنامه ها حذف شوند؟"
|
||||
@ -323,7 +327,7 @@
|
||||
"other": "{} و {} برنامه دیگر به روز شدند."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} and 1 more app may have been updated.",
|
||||
"other": "{} and {} more apps may have been updated."
|
||||
"one": "{} و 1 برنامه دیگر ممکن است به روز شده باشند.",
|
||||
"other": "ممکن است {} و {} برنامه های دیگر به روز شده باشند."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Pas installé",
|
||||
"estimateInBrackets": "(Estimation)",
|
||||
"selectAll": "Tout sélectionner",
|
||||
"deselectN": "Déselectionner {}",
|
||||
"deselectX": "Déselectionner {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} sera supprimé d'Obtainium mais restera installé sur l'appareil.",
|
||||
"removeSelectedAppsQuestion": "Supprimer les applications sélectionnées ?",
|
||||
"removeSelectedApps": "Supprimer les applications sélectionnées",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)",
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check for updates on startup",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
||||
@ -256,6 +256,7 @@
|
||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||
"pickExportDir": "Pick Export Directory",
|
||||
"autoExportOnChanges": "Auto-export on changes",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "Téléchargement {}",
|
||||
"completeAppInstallationNotifChannel": "Installation complète de l'application",
|
||||
"checkingForUpdatesNotifChannel": "Vérification des mises à jour",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Supprimer l'application ?",
|
||||
"other": "Supprimer les applications ?"
|
||||
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Nem telepített",
|
||||
"estimateInBrackets": "(Becslés)",
|
||||
"selectAll": "Mindet kiválaszt",
|
||||
"deselectN": "Törölje {} kijelölését",
|
||||
"deselectX": "Törölje {} kijelölését",
|
||||
"xWillBeRemovedButRemainInstalled": "A(z) {} el lesz távolítva az Obtainiumból, de továbbra is telepítve marad az eszközön.",
|
||||
"removeSelectedAppsQuestion": "Eltávolítja a kiválasztott appokat?",
|
||||
"removeSelectedApps": "Távolítsa el a kiválasztott appokat",
|
||||
@ -113,7 +113,7 @@
|
||||
"followSystem": "Rendszer szerint",
|
||||
"obtainium": "Obtainium",
|
||||
"materialYou": "Material You",
|
||||
"useBlackTheme": "Használjon tiszta fekete sötét témát",
|
||||
"useBlackTheme": "Használjon teljesen fekete sötét témát",
|
||||
"appSortBy": "App rendezés...",
|
||||
"authorName": "Szerző/Név",
|
||||
"nameAuthor": "Név/Szerző",
|
||||
@ -194,7 +194,7 @@
|
||||
"categories": "Kategóriák",
|
||||
"category": "Kategória",
|
||||
"noCategory": "Nincs kategória",
|
||||
"noCategories": "No Categories",
|
||||
"noCategories": "Nincsenek kategóriák",
|
||||
"deleteCategoryQuestion": "Törli a kategóriát?",
|
||||
"categoryDeleteWarning": "A(z) {} összes app kategorizálatlan állapotba kerül.",
|
||||
"addCategory": "Új kategória",
|
||||
@ -215,7 +215,7 @@
|
||||
"versionDetection": "Verzió érzékelés",
|
||||
"standardVersionDetection": "Alapért. verzió érzékelés",
|
||||
"groupByCategory": "Csoportosítás Kategória alapján",
|
||||
"autoApkFilterByArch": "Ha lehetséges, próbálja CPU architektúra szerint szűrni az APK-okat",
|
||||
"autoApkFilterByArch": "Ha lehetséges, próbálja CPU architektúra szerint szűrni az APK-kat",
|
||||
"overrideSource": "Forrás felülbírálása",
|
||||
"dontShowAgain": "Ne mutassa ezt újra",
|
||||
"dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést és jobb APK felfedezés)",
|
||||
"about": "Rólunk",
|
||||
"requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
|
||||
"requiresCredentialsInSettings": "{}: Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
|
||||
"checkOnStart": "Egyszer az alkalmazás indításakor is",
|
||||
"tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból",
|
||||
"removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása",
|
||||
@ -245,8 +245,8 @@
|
||||
"backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.",
|
||||
"backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.",
|
||||
"verifyLatestTag": "Ellenőrizze a „legújabb” címkét",
|
||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First",
|
||||
"intermediateLinkNotFound": "Intermediate link not found",
|
||||
"intermediateLinkRegex": "Szűrés egy 'közvetítő' linkre, amelyet először meg kell látogatni",
|
||||
"intermediateLinkNotFound": "Közvetítő link nem található",
|
||||
"exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)",
|
||||
"bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n",
|
||||
"autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása",
|
||||
@ -255,6 +255,7 @@
|
||||
"highlightTouchTargets": "Emelje ki a kevésbé nyilvánvaló érintési célokat",
|
||||
"pickExportDir": "Válassza az Exportálási könyvtárat",
|
||||
"autoExportOnChanges": "Auto-exportálás a változások után",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel",
|
||||
"trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t",
|
||||
"dontSortReleasesList": "Az API-ból származó kiadási sorrend megőrzése",
|
||||
@ -263,9 +264,9 @@
|
||||
"bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.",
|
||||
"enableBackgroundUpdates": "Frissítések a háttérben",
|
||||
"runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"versionExtractWholePage": "Alkalmazza a Version Extraction Regex-et az egész oldalra",
|
||||
"installing": "Telepítés",
|
||||
"skipUpdateNotifications": "A frissítési értesítések kihagyása",
|
||||
"updatesAvailableNotifChannel": "Frissítések érhetők el",
|
||||
"appsUpdatedNotifChannel": "Alkalmazások frissítve",
|
||||
"appsPossiblyUpdatedNotifChannel": "App frissítési kísérlet",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "{} letöltés",
|
||||
"completeAppInstallationNotifChannel": "Teljes app telepítés",
|
||||
"checkingForUpdatesNotifChannel": "Frissítések keresése",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Csak a telepített és a csak követhető appokat ellenőrizze frissítésekért",
|
||||
"supportFixedAPKURL": "Támogatja a rögzített APK URL-eket",
|
||||
"selectX": "Kiválaszt {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Eltávolítja az alkalmazást?",
|
||||
"other": "Eltávolítja az alkalmazást?"
|
||||
@ -326,4 +330,4 @@
|
||||
"one": "{} és 1 további alkalmazás is frissült.",
|
||||
"other": "{} és {} további alkalmazás is frissült."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
"unexpectedError": "Errore imprevisto",
|
||||
"ok": "Va bene",
|
||||
"and": "e",
|
||||
"githubPATLabel": "GitHub Personal Access Token (diminuisce limite di traffico)",
|
||||
"githubPATLabel": "GitHub Personal Access Token (aumenta limite di traffico)",
|
||||
"includePrereleases": "Includi prerelease",
|
||||
"fallbackToOlderReleases": "Ripiega su release precedenti",
|
||||
"filterReleaseTitlesByRegEx": "Filtra release con espressioni regolari",
|
||||
@ -51,17 +51,17 @@
|
||||
"percentProgress": "Avanzamento: {}%",
|
||||
"pleaseWait": "In attesa",
|
||||
"updateAvailable": "Aggiornamento disponibile",
|
||||
"estimateInBracketsShort": "(prev.)",
|
||||
"estimateInBracketsShort": "(stim.)",
|
||||
"notInstalled": "Non installato",
|
||||
"estimateInBrackets": "(previsto)",
|
||||
"estimateInBrackets": "(stimato)",
|
||||
"selectAll": "Seleziona tutto",
|
||||
"deselectN": "Deseleziona {}",
|
||||
"deselectX": "Deseleziona {}",
|
||||
"xWillBeRemovedButRemainInstalled": "Verà effettuata la rimozione di {}, ma non la disinstallazione.",
|
||||
"removeSelectedAppsQuestion": "Rimuovere le app selezionate?",
|
||||
"removeSelectedApps": "Rimuovi le app selezionate",
|
||||
"updateX": "Aggiorna {}",
|
||||
"installX": "Installa {}",
|
||||
"markXTrackOnlyAsUpdated": "Contrassegna {}\n(Solo-Monitoraggio)\ncome aggiornato",
|
||||
"markXTrackOnlyAsUpdated": "Contrassegna {}\n(Solo-Monitoraggio)\ncome aggiornata",
|
||||
"changeX": "Modifica {}",
|
||||
"installUpdateApps": "Installa/Aggiorna app",
|
||||
"installUpdateSelectedApps": "Installa/Aggiorna le app selezionate",
|
||||
@ -128,7 +128,7 @@
|
||||
"pinUpdates": "Fissa aggiornamenti disponibili in alto",
|
||||
"updates": "Aggiornamenti",
|
||||
"sourceSpecific": "Specifiche per la fonte",
|
||||
"appSource": "Sorgente dell'app",
|
||||
"appSource": "Codice dell'app",
|
||||
"noLogs": "Nessun log",
|
||||
"appLogs": "Log dell'app",
|
||||
"close": "Chiudi",
|
||||
@ -169,7 +169,7 @@
|
||||
"installedVersionX": "Versione installata: {}",
|
||||
"lastUpdateCheckX": "Ultimo controllo degli aggiornamenti: {}",
|
||||
"remove": "Rimuovi",
|
||||
"yesMarkUpdated": "Sì, contrassegna come aggiornato",
|
||||
"yesMarkUpdated": "Sì, contrassegna come aggiornata",
|
||||
"fdroid": "F-Droid ufficiale",
|
||||
"appIdOrName": "ID o nome dell'app",
|
||||
"appId": "ID dell'app",
|
||||
@ -180,9 +180,9 @@
|
||||
"steamMobile": "Steam Mobile",
|
||||
"steamChat": "Steam Chat",
|
||||
"install": "Installa",
|
||||
"markInstalled": "Contrassegna come installato",
|
||||
"markInstalled": "Contrassegna come installata",
|
||||
"update": "Aggiorna",
|
||||
"markUpdated": "Contrassegna come aggiornato",
|
||||
"markUpdated": "Contrassegna come aggiornata",
|
||||
"additionalOptions": "Opzioni aggiuntive",
|
||||
"disableVersionDetection": "Disattiva il rilevamento della versione",
|
||||
"noVersionDetectionExplanation": "Questa opzione dovrebbe essere usata solo per le app la cui versione non viene rilevata correttamente.",
|
||||
@ -221,59 +221,63 @@
|
||||
"dontShowTrackOnlyWarnings": "Non mostrare gli avvisi 'Solo-Monitoraggio'",
|
||||
"dontShowAPKOriginWarnings": "Non mostrare gli avvisi di origine dell'APK",
|
||||
"moveNonInstalledAppsToBottom": "Sposta le app non installate in fondo alla lista",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(attiva la ricerca and Better APK Discovery)",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(attiva la ricerca e migliora la rilevazione di apk)",
|
||||
"about": "Informazioni",
|
||||
"requiresCredentialsInSettings": "Servono credenziali aggiuntive (in Impostazioni)",
|
||||
"requiresCredentialsInSettings": "{}: Servono credenziali aggiuntive (in Impostazioni)",
|
||||
"checkOnStart": "Controlla una volta all'avvio",
|
||||
"tryInferAppIdFromCode": "Prova a dedurre l'ID dell'app dal codice sorgente",
|
||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
||||
"pickHighestVersionCode": "Auto-select highest version code APK",
|
||||
"checkUpdateOnDetailPage": "Check for updates on opening an App detail page",
|
||||
"disablePageTransitions": "Disable page transition animations",
|
||||
"reversePageTransitions": "Reverse page transition animations",
|
||||
"minStarCount": "Minimum Star Count",
|
||||
"addInfoBelow": "Add this info below.",
|
||||
"addInfoInSettings": "Add this info in the Settings.",
|
||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
||||
"appsPossiblyUpdated": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
|
||||
"xWasPossiblyUpdatedToY": "{} may have been updated to {}.",
|
||||
"enableBackgroundUpdates": "Enable background updates",
|
||||
"backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.",
|
||||
"backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.",
|
||||
"verifyLatestTag": "Verify the 'latest' tag",
|
||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First",
|
||||
"intermediateLinkNotFound": "Intermediate link not found",
|
||||
"exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)",
|
||||
"bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
|
||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
||||
"matchGroupToUse": "Match Group to Use",
|
||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||
"pickExportDir": "Pick Export Directory",
|
||||
"autoExportOnChanges": "Auto-export on changes",
|
||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
"reverseSort": "Reverse sorting",
|
||||
"debugMenu": "Debug Menu",
|
||||
"bgTaskStarted": "Background task started - check logs.",
|
||||
"runBgCheckNow": "Run Background Update Check Now",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"removeOnExternalUninstall": "Rimuovi automaticamente app disinstallate esternamente",
|
||||
"pickHighestVersionCode": "Auto-seleziona APK con version code più alto",
|
||||
"checkUpdateOnDetailPage": "Controlla aggiornamenti all'apertura dei dettagli dell'app",
|
||||
"disablePageTransitions": "Disattiva animazioni di transizione pagina",
|
||||
"reversePageTransitions": "Inverti animazioni di transizione pagina",
|
||||
"minStarCount": "Numero minimo di stelle",
|
||||
"addInfoBelow": "Aggiungi questa info sotto.",
|
||||
"addInfoInSettings": "Aggiungi questa info nelle impostazioni.",
|
||||
"githubSourceNote": "Il limite di ricerca GitHub può essere evitato usando una chiave API.",
|
||||
"gitlabSourceNote": "L'estrazione di APK da GitLab potrebbe non funzionare senza chiave API.",
|
||||
"sortByFileNamesNotLinks": "Ordina per nome del file invece dei link completi",
|
||||
"filterReleaseNotesByRegEx": "Filtra le note di rilascio con espressione regolare",
|
||||
"customLinkFilterRegex": "Filtra link APK personalizzato con espressione regolare (predefinito '.apk$')",
|
||||
"appsPossiblyUpdated": "Aggiornamenti app tentati",
|
||||
"appsPossiblyUpdatedNotifDescription": "Notifica all'utente che sono stati potenzialmente applicati in secondo piano aggiornamenti a una o più app",
|
||||
"xWasPossiblyUpdatedToY": "{} potrebbe essere stata aggiornata alla {}.",
|
||||
"enableBackgroundUpdates": "Attiva aggiornamenti in secondo piano",
|
||||
"backgroundUpdateReqsExplanation": "Gli aggiornamenti in secondo piano potrebbero non essere possibili per tutte le app.",
|
||||
"backgroundUpdateLimitsExplanation": "La riuscita di un'installazione in secondo piano può essere determinata solo quando viene aperto Obtainium.",
|
||||
"verifyLatestTag": "Verifica l'etichetta 'Latest'",
|
||||
"intermediateLinkRegex": "Filtra un link 'Intermedio' da visitare prima",
|
||||
"intermediateLinkNotFound": "Link intermedio non trovato",
|
||||
"exemptFromBackgroundUpdates": "Esente da aggiornamenti in secondo piano (se attivo)",
|
||||
"bgUpdatesOnWiFiOnly": "Disattiva aggiornamenti in secondo piano quando non si usa il WiFi",
|
||||
"autoSelectHighestVersionCode": "Auto-seleziona APK con versionCode più alto",
|
||||
"versionExtractionRegEx": "RegEx di estrazione versione",
|
||||
"matchGroupToUse": "Gruppo da usare",
|
||||
"highlightTouchTargets": "Evidenzia elementi toccabili meno ovvi",
|
||||
"pickExportDir": "Scegli cartella esp.",
|
||||
"autoExportOnChanges": "Auto-esporta dopo modifiche",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filtra versioni con espressione regolare",
|
||||
"trySelectingSuggestedVersionCode": "Prova a selezionare APK con versionCode suggerito",
|
||||
"dontSortReleasesList": "Conserva l'ordine di release da API",
|
||||
"reverseSort": "Ordine inverso",
|
||||
"debugMenu": "Menu di debug",
|
||||
"bgTaskStarted": "Attività in secondo piano iniziata - controllo log.",
|
||||
"runBgCheckNow": "Inizia aggiornamento in secondo piano ora",
|
||||
"versionExtractWholePage": "Applica regex di estrazione versione a tutta la pagina",
|
||||
"installing": "Installazione",
|
||||
"skipUpdateNotifications": "Salta notifiche di aggiornamento",
|
||||
"updatesAvailableNotifChannel": "Aggiornamenti disponibili",
|
||||
"appsUpdatedNotifChannel": "App aggiornate",
|
||||
"appsPossiblyUpdatedNotifChannel": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifChannel": "Aggiornamenti app tentati",
|
||||
"errorCheckingUpdatesNotifChannel": "Controllo degli errori per gli aggiornamenti",
|
||||
"appsRemovedNotifChannel": "App rimosse",
|
||||
"downloadingXNotifChannel": "Scaricamento di {} in corso",
|
||||
"completeAppInstallationNotifChannel": "Completa l'installazione dell'app",
|
||||
"checkingForUpdatesNotifChannel": "Controllo degli aggiornamenti in corso",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Cerca aggiornamenti solo per app installate e app in Solo-Monitoraggio",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Rimuovere l'app?",
|
||||
"other": "Rimuovere le app?"
|
||||
@ -323,7 +327,7 @@
|
||||
"other": "{} e altre {} app sono state aggiornate."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} and 1 more app may have been updated.",
|
||||
"other": "{} and {} more apps may have been updated."
|
||||
"one": "{} e un'altra app potrebbero essere state aggiornate.",
|
||||
"other": "{} e altre {} app potrebbero essere state aggiornate."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "未インストール",
|
||||
"estimateInBrackets": "(推定)",
|
||||
"selectAll": "すべて選択",
|
||||
"deselectN": "{}件の選択を解除",
|
||||
"deselectX": "{}件の選択を解除",
|
||||
"xWillBeRemovedButRemainInstalled": "{} はObtainiumから削除されますが、デバイスにはインストールされたままです。",
|
||||
"removeSelectedAppsQuestion": "選択したアプリを削除しますか?",
|
||||
"removeSelectedApps": "選択したアプリを削除する",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "未インストールのアプリをアプリ一覧の下部に移動させる",
|
||||
"gitlabPATLabel": "GitLab パーソナルアクセストークン\n(検索とより良いAPK検出の有効化)",
|
||||
"about": "概要",
|
||||
"requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)",
|
||||
"requiresCredentialsInSettings": "{}: これには追加の認証が必要です (設定にて)",
|
||||
"checkOnStart": "起動時にアップデートを確認する",
|
||||
"tryInferAppIdFromCode": "ソースコードからApp IDを推測する",
|
||||
"removeOnExternalUninstall": "外部でアンインストールされたアプリを自動的に削除する",
|
||||
@ -256,16 +256,17 @@
|
||||
"highlightTouchTargets": "目立たないタップ可能な対象をハイライトする",
|
||||
"pickExportDir": "エクスポートディレクトリを選択",
|
||||
"autoExportOnChanges": "変更があった際に自動でエクスポートする",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "正規表現でバージョンをフィルタリングする",
|
||||
"trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
"reverseSort": "Reverse sorting",
|
||||
"debugMenu": "Debug Menu",
|
||||
"bgTaskStarted": "Background task started - check logs.",
|
||||
"runBgCheckNow": "Run Background Update Check Now",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"dontSortReleasesList": "APIからのリリース順を保持する",
|
||||
"reverseSort": "逆順ソート",
|
||||
"debugMenu": "デバッグメニュー",
|
||||
"bgTaskStarted": "バックグラウンドタスクが開始されました - ログを確認してください。",
|
||||
"runBgCheckNow": "今すぐバックグラウンドでのアップデート確認を開始する",
|
||||
"versionExtractWholePage": "バージョン抽出の正規表現をページ全体に適用する",
|
||||
"installing": "インストール中",
|
||||
"skipUpdateNotifications": "アップデート通知を行わない",
|
||||
"updatesAvailableNotifChannel": "アップデートが利用可能",
|
||||
"appsUpdatedNotifChannel": "アプリをアップデートしました",
|
||||
"appsPossiblyUpdatedNotifChannel": "アプリのアップデートを試行",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "{} をダウンロード中",
|
||||
"completeAppInstallationNotifChannel": "アプリのインストールを完了する",
|
||||
"checkingForUpdatesNotifChannel": "アップデートを確認中",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "インストール済みのアプリと「追跡のみ」のアプリのアップデートのみを確認する",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "アプリを削除しますか?",
|
||||
"other": "アプリを削除しますか?"
|
||||
|
333
assets/translations/nl.json
Normal file
333
assets/translations/nl.json
Normal file
@ -0,0 +1,333 @@
|
||||
{
|
||||
"invalidURLForSource": "Geen valide {} app URL",
|
||||
"noReleaseFound": "Kan geen geschikte release vinden",
|
||||
"noVersionFound": "Kan de versie niet bepalen",
|
||||
"urlMatchesNoSource": "URL komt niet overeen met bekende bron",
|
||||
"cantInstallOlderVersion": "Kan geen oudere versie van de app installeren",
|
||||
"appIdMismatch": "Gedownloade pakket-ID komt niet overeen met de bestaande app-ID",
|
||||
"functionNotImplemented": "Deze class heeft deze functie niet geïmplementeerd.",
|
||||
"placeholder": "Plaatshouder",
|
||||
"someErrors": "Er zijn enkele fouten opgetreden",
|
||||
"unexpectedError": "Onverwachte fout",
|
||||
"ok": "Ok",
|
||||
"and": "en",
|
||||
"githubPATLabel": "GitHub Personal Access Token\n(Verhoogt limiet aantal verzoeken)",
|
||||
"includePrereleases": "Bevat prereleases",
|
||||
"fallbackToOlderReleases": "Terugvallen op oudere releases",
|
||||
"filterReleaseTitlesByRegEx": "Filter release-titels met reguliere expressies.",
|
||||
"invalidRegEx": "Ongeldige reguliere expressie",
|
||||
"noDescription": "Geen omschrijving",
|
||||
"cancel": "Annuleer",
|
||||
"continue": "Ga verder",
|
||||
"requiredInBrackets": "(Verplicht)",
|
||||
"dropdownNoOptsError": "FOUTMELDING: DROPDOWN MOET TENMINSTE ÉÉN OPT HEBBEN",
|
||||
"colour": "Kleur",
|
||||
"githubStarredRepos": "GitHub Starred Repos",
|
||||
"uname": "Gebruikersnaam",
|
||||
"wrongArgNum": "Onjuist aantal argumenten verstrekt.",
|
||||
"xIsTrackOnly": "{} is Track-Only",
|
||||
"source": "Bron",
|
||||
"app": "App",
|
||||
"appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Track-Only'.",
|
||||
"youPickedTrackOnly": "Je hebt de 'Track-Only' optie geselecteerd.",
|
||||
"trackOnlyAppDescription": "De app zal worden gevolgd voor updates, maar Obtainium zal niet in staat zijn om deze te downloaden of te installeren.",
|
||||
"cancelled": "Geannuleerd",
|
||||
"appAlreadyAdded": "App al toegevoegd",
|
||||
"alreadyUpToDateQuestion": "Is de app al up-to-date?",
|
||||
"addApp": "App toevoegen",
|
||||
"appSourceURL": "App bron URL",
|
||||
"error": "Foutmelding",
|
||||
"add": "Toevoegen",
|
||||
"searchSomeSourcesLabel": "Zoeken (Alleen sommige bronnen)",
|
||||
"search": "Zoeken",
|
||||
"additionalOptsFor": "Aanvullende opties voor {}",
|
||||
"supportedSources": "Ondersteunde bronnen",
|
||||
"trackOnlyInBrackets": "(Track-Only)",
|
||||
"searchableInBrackets": "(Doorzoekbaar)",
|
||||
"appsString": "Apps",
|
||||
"noApps": "Geen Apps",
|
||||
"noAppsForFilter": "Geen Apps voor filter",
|
||||
"byX": "Door {}",
|
||||
"percentProgress": "Vooruitgang: {}%",
|
||||
"pleaseWait": "Even geduld",
|
||||
"updateAvailable": "Update beschikbaar",
|
||||
"estimateInBracketsShort": "(Ong.)",
|
||||
"notInstalled": "Niet geinstalleerd",
|
||||
"estimateInBrackets": "(Ongeveer)",
|
||||
"selectAll": "Selecteer alles",
|
||||
"deselectX": "Deselecteer {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} zal worden verwijderd uit Obtainium, maar blijft geïnstalleerd op het apparaat.",
|
||||
"removeSelectedAppsQuestion": "Geselecteerde apps verwijderen??",
|
||||
"removeSelectedApps": "Geselecteerde apps verwijderen",
|
||||
"updateX": "Update {}",
|
||||
"installX": "Installeer {}",
|
||||
"markXTrackOnlyAsUpdated": "Markeer {}\n(Track-Only)\nals up-to-date",
|
||||
"changeX": "Verander {}",
|
||||
"installUpdateApps": "Installeer/Update apps",
|
||||
"installUpdateSelectedApps": "Installeer/Update geselecteerde apps",
|
||||
"markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als up-to-date?",
|
||||
"no": "Nee",
|
||||
"yes": "Ja",
|
||||
"markSelectedAppsUpdated": "Markeer geselecteerde aps als up-to-date",
|
||||
"pinToTop": "Vastzetten aan de bovenkant",
|
||||
"unpinFromTop": "Losmaken van de bovenkant",
|
||||
"resetInstallStatusForSelectedAppsQuestion": "Installatiestatus resetten voor geselecteerde apps?",
|
||||
"installStatusOfXWillBeResetExplanation": "De installatiestatus van alle geselecteerde apps zal worden gereset.\n\nDit kan helpen wanneer de versie van de app die in Obtainium wordt weergegeven onjuist is vanwege mislukte updates of andere problemen.",
|
||||
"shareSelectedAppURLs": "Deel geselecteerde app URL's",
|
||||
"resetInstallStatus": "Reset installatiestatus",
|
||||
"more": "Meer",
|
||||
"removeOutdatedFilter": "Verwijder out-of-date app filter",
|
||||
"showOutdatedOnly": "Toon alleen out-of-date apps",
|
||||
"filter": "Filter",
|
||||
"filterActive": "Filter *",
|
||||
"filterApps": "Filter apps",
|
||||
"appName": "App naam",
|
||||
"author": "Auteur",
|
||||
"upToDateApps": "Up-to-date apps",
|
||||
"nonInstalledApps": "Niet-geïnstalleerde apps",
|
||||
"importExport": "Import/Export",
|
||||
"settings": "Instellingen",
|
||||
"exportedTo": "Geëxporteerd naar {}",
|
||||
"obtainiumExport": "Obtainium export",
|
||||
"invalidInput": "Ongeldige invoer",
|
||||
"importedX": "Geïmporteerd {}",
|
||||
"obtainiumImport": "Obtainium import",
|
||||
"importFromURLList": "Importeer van URL-lijsten",
|
||||
"searchQuery": "Zoekopdracht",
|
||||
"appURLList": "App URL-lijst",
|
||||
"line": "Lijn",
|
||||
"searchX": "Zoek {}",
|
||||
"noResults": "Geen resultaten gevonden",
|
||||
"importX": "Import {}",
|
||||
"importedAppsIdDisclaimer": "Geïmporteerde apps kunnen mogelijk onjuist worden weergegeven als \"Niet geïnstalleerd\".\nOm dit op te lossen, herinstalleer ze via Obtainium.\nDit zou geen invloed moeten hebben op app-gegevens.\n\nDit heeft alleen invloed op URL- en importmethoden van derden.",
|
||||
"importErrors": "Import foutmeldingen",
|
||||
"importedXOfYApps": "{} van {} apps geïmporteerd.",
|
||||
"followingURLsHadErrors": "De volgende URL's bevatten fouten:",
|
||||
"okay": "Ok",
|
||||
"selectURL": "Selecteer URL",
|
||||
"selectURLs": "Selecteer URL's",
|
||||
"pick": "Kies",
|
||||
"theme": "Thema",
|
||||
"dark": "Donker",
|
||||
"light": "Licht",
|
||||
"followSystem": "Volg systeem",
|
||||
"obtainium": "Obtainium",
|
||||
"materialYou": "Material You",
|
||||
"useBlackTheme": "Gebruik zwart thema",
|
||||
"appSortBy": "App sorteren op",
|
||||
"authorName": "Auteur/Naam",
|
||||
"nameAuthor": "Naam/Auteur",
|
||||
"asAdded": "Zoals toegevoegd",
|
||||
"appSortOrder": "App sorteervolgorde",
|
||||
"ascending": "Oplopend",
|
||||
"descending": "Aflopend",
|
||||
"bgUpdateCheckInterval": "Frequentie voor achtergrondupdatecontrole",
|
||||
"neverManualOnly": "Nooit - Alleen handmatig",
|
||||
"appearance": "Weergave",
|
||||
"showWebInAppView": "Toon de bronwebpagina in app-weergave",
|
||||
"pinUpdates": "Updates bovenaan in de apps-weergave vastpinnen",
|
||||
"updates": "Updates",
|
||||
"sourceSpecific": "Bron-specifiek",
|
||||
"appSource": "App bron",
|
||||
"noLogs": "Geen logs",
|
||||
"appLogs": "App logs",
|
||||
"close": "Sluiten",
|
||||
"share": "Delen",
|
||||
"appNotFound": "App niet gevonden",
|
||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||
"pickAnAPK": "Kies een APK",
|
||||
"appHasMoreThanOnePackage": "{} heeft meer dan één package:",
|
||||
"deviceSupportsXArch": "Jouw apparaat support de {} CPU-architectuur.",
|
||||
"deviceSupportsFollowingArchs": "Je apparaat ondersteunt de volgende CPU-architecturen:",
|
||||
"warning": "Waarschuwing",
|
||||
"sourceIsXButPackageFromYPrompt": "De appbron is '{}' maar de release package komt van '{}'. Doorgaan?",
|
||||
"updatesAvailable": "Updates beschikbaar",
|
||||
"updatesAvailableNotifDescription": "Stelt de gebruiker op de hoogte dat er updates beschikbaar zijn voor één of meer apps die worden bijgehouden door Obtainium.",
|
||||
"noNewUpdates": "Geen nieuwe updates.",
|
||||
"xHasAnUpdate": "{} heeft een update.",
|
||||
"appsUpdated": "Apps bijgewerkt",
|
||||
"appsUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps in de achtergrond zijn toegepast.",
|
||||
"xWasUpdatedToY": "{} is bijgewerkt naar {}.",
|
||||
"errorCheckingUpdates": "Fout bij het controleren op updates",
|
||||
"errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer het controleren op updates in de achtergrond mislukt",
|
||||
"appsRemoved": "Apps verwijderd",
|
||||
"appsRemovedNotifDescription": "Stelt de gebruiker op de hoogte dat één of meer apps zijn verwijderd vanwege fouten tijdens het laden ervan",
|
||||
"xWasRemovedDueToErrorY": "{} is verwijderd vanwege deze foutmelding: {}",
|
||||
"completeAppInstallation": "Complete app installatie",
|
||||
"obtainiumMustBeOpenToInstallApps": "Obtainium moet geopend zijn om apps te installeren",
|
||||
"completeAppInstallationNotifDescription": "Vraagt de gebruiker om terug te keren naar Obtainium om de installatie van een app af te ronden",
|
||||
"checkingForUpdates": "Controleren op updates",
|
||||
"checkingForUpdatesNotifDescription": "Tijdelijke melding die verschijnt tijdens het controleren op updates",
|
||||
"pleaseAllowInstallPerm": "Sta Obtainium toe om apps te installeren",
|
||||
"trackOnly": "Track-Only",
|
||||
"errorWithHttpStatusCode": "Foutmelding {}",
|
||||
"versionCorrectionDisabled": "Versiecorrectie uitgeschakeld (de plug-in lijkt niet te werken)",
|
||||
"unknown": "Onbekend",
|
||||
"none": "Geen",
|
||||
"never": "Nooit",
|
||||
"latestVersionX": "Laatste versie: {}",
|
||||
"installedVersionX": "Geïnstalleerde versie: {}",
|
||||
"lastUpdateCheckX": "Laatste updatecontrole: {}",
|
||||
"remove": "Verwijderen",
|
||||
"yesMarkUpdated": "Ja, markeer als bijgewerkt",
|
||||
"fdroid": "F-Droid Official",
|
||||
"appIdOrName": "App ID of naam",
|
||||
"appId": "App ID",
|
||||
"appWithIdOrNameNotFound": "Er werd geen app gevonden met dat ID of die naam",
|
||||
"reposHaveMultipleApps": "Repositories kunnen meerdere apps bevatten",
|
||||
"fdroidThirdPartyRepo": "F-Droid Third-Party Repo",
|
||||
"steam": "Steam",
|
||||
"steamMobile": "Steam Mobile",
|
||||
"steamChat": "Steam Chat",
|
||||
"install": "Installeren",
|
||||
"markInstalled": "Als geïnstalleerd markere",
|
||||
"update": "Update",
|
||||
"markUpdated": "Markeren als bijgewerkt",
|
||||
"additionalOptions": "Aanvullende opties",
|
||||
"disableVersionDetection": "Versieherkenning uitschakelen",
|
||||
"noVersionDetectionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt.",
|
||||
"downloadingX": "Downloaden {}",
|
||||
"downloadNotifDescription": "Stelt de gebruiker op de hoogte van de voortgang bij het downloaden van een app",
|
||||
"noAPKFound": "Geen APK gevonden",
|
||||
"noVersionDetection": "Geen versieherkenning",
|
||||
"categorize": "Categoriseren",
|
||||
"categories": "Categorieën",
|
||||
"category": "Categorie",
|
||||
"noCategory": "Geen categorie",
|
||||
"noCategories": "Geen categorieën",
|
||||
"deleteCategoriesQuestion": "Categorieën verwijderen?",
|
||||
"categoryDeleteWarning": "Alle apps in verwijderde categorieën worden teruggezet naar 'ongecategoriseerd'.",
|
||||
"addCategory": "Categorie toevoegen",
|
||||
"label": "Label",
|
||||
"language": "Taal",
|
||||
"copiedToClipboard": "Gekopieerd naar klembord",
|
||||
"storagePermissionDenied": "Toegang tot opslag geweigerd",
|
||||
"selectedCategorizeWarning": "Dit zal eventuele bestaande categorie-instellingen voor de geselecteerde apps vervangen.",
|
||||
"filterAPKsByRegEx": "Filter APK's op reguliere expressie",
|
||||
"removeFromObtainium": "Verwijder van Obtainium",
|
||||
"uninstallFromDevice": "Verwijder van apparaat",
|
||||
"onlyWorksWithNonVersionDetectApps": "Werkt alleen voor apps waarbij versieherkenning is uitgeschakeld.",
|
||||
"releaseDateAsVersion": "Gebruik de releasedatum als versie",
|
||||
"releaseDateAsVersionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt, maar waar wel een releasedatum beschikbaar is.",
|
||||
"changes": "Veranderingen",
|
||||
"releaseDate": "Releasedatum",
|
||||
"importFromURLsInFile": "Importeren vanaf URL's in een bestand (zoals OPML)",
|
||||
"versionDetection": "Versieherkenning",
|
||||
"standardVersionDetection": "Standaard versieherkenning",
|
||||
"groupByCategory": "Groepeer op categorie",
|
||||
"autoApkFilterByArch": "Poging om APK's te filteren op CPU-architectuur indien mogelijk",
|
||||
"overrideSource": "Bron overschrijven",
|
||||
"dontShowAgain": "Don't show this again",
|
||||
"dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven",
|
||||
"dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven",
|
||||
"moveNonInstalledAppsToBottom": "Verplaats niet-geïnstalleerde apps naar de onderkant van de apps-weergave",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Maakt het mogelijk beter te zoeken naar APK's)",
|
||||
"about": "Over",
|
||||
"requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)",
|
||||
"checkOnStart": "Controleren op updates bij opstarten",
|
||||
"tryInferAppIdFromCode": "Probeer de app-ID af te leiden uit de broncode",
|
||||
"removeOnExternalUninstall": "Automatisch extern verwijderde apps verwijderen",
|
||||
"pickHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
|
||||
"checkUpdateOnDetailPage": "Controleren op updates bij het openen van een app-detailpagina",
|
||||
"disablePageTransitions": "Schakel overgangsanimaties tussen pagina's uit",
|
||||
"reversePageTransitions": "Omgekeerde overgangsanimaties tussen pagina's",
|
||||
"minStarCount": "Minimale Github Stars",
|
||||
"addInfoBelow": "Voeg deze informatie hieronder toe.",
|
||||
"addInfoInSettings": "Voeg deze informatie toe in de instellingen.",
|
||||
"githubSourceNote": "Beperkingen van GitHub kunnen worden vermeden door het gebruik van een API-sleutel.",
|
||||
"gitlabSourceNote": "GitLab APK-extractie werkt mogelijk niet zonder een API-sleutel.",
|
||||
"sortByFileNamesNotLinks": "Sorteren op bestandsnamen in plaats van volledige links.",
|
||||
"filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.",
|
||||
"customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').",
|
||||
"appsPossiblyUpdated": "Poging tot app-updates",
|
||||
"appsPossiblyUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps mogelijk in de achtergrond zijn toegepast",
|
||||
"xWasPossiblyUpdatedToY": "{} mogelijk bijgewerkt naar {}.",
|
||||
"enableBackgroundUpdates": "Achtergrondupdates inschakelen",
|
||||
"backgroundUpdateReqsExplanation": "Achtergrondupdates zijn mogelijk niet voor alle apps mogelijk.",
|
||||
"backgroundUpdateLimitsExplanation": "Het succes van een installatie in de achtergrond kan alleen worden bepaald wanneer Obtainium is geopend.",
|
||||
"verifyLatestTag": "Verifieer de 'Laatste'-tag",
|
||||
"intermediateLinkRegex": "Filter voor een 'tussenliggende' link om eerst te bezoeken",
|
||||
"intermediateLinkNotFound": "Tussenliggende link niet gevonden",
|
||||
"exemptFromBackgroundUpdates": "Vrijgesteld van achtergrondupdates (indien ingeschakeld)",
|
||||
"bgUpdatesOnWiFiOnly": "Achtergrondupdates uitschakelen wanneer niet verbonden met WiFi",
|
||||
"autoSelectHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
|
||||
"versionExtractionRegEx": "Reguliere expressie voor versie-extractie",
|
||||
"matchGroupToUse": "Overeenkomende groep om te gebruiken voor de reguliere expressie voor versie-extractie",
|
||||
"highlightTouchTargets": "Markeer minder voor de hand liggende aanraakdoelen.",
|
||||
"pickExportDir": "Kies de exportmap",
|
||||
"autoExportOnChanges": "Automatisch exporteren bij wijzigingen",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filter versies met een reguliere expressie",
|
||||
"trySelectingSuggestedVersionCode": "Probeer de voorgestelde versiecode APK te selecteren",
|
||||
"dontSortReleasesList": "Volgorde van releases behouden vanuit de API",
|
||||
"reverseSort": "Sortering omkeren",
|
||||
"debugMenu": "Debug menu",
|
||||
"bgTaskStarted": "Achtergrondtaak gestart - controleer de logs.",
|
||||
"runBgCheckNow": "Voer nu een achtergrondupdatecontrole uit",
|
||||
"versionExtractWholePage": "De reguliere expressie voor versie-extractie toepassen op de hele pagina",
|
||||
"installing": "Installeren",
|
||||
"skipUpdateNotifications": "Updatemeldingen overslaan",
|
||||
"updatesAvailableNotifChannel": "Updates beschikbaar",
|
||||
"appsUpdatedNotifChannel": "Apps bijgewerkt",
|
||||
"appsPossiblyUpdatedNotifChannel": "Poging tot app-updates",
|
||||
"errorCheckingUpdatesNotifChannel": "Foutcontrole bij het zoeken naar updates",
|
||||
"appsRemovedNotifChannel": "Apps verwijderd",
|
||||
"downloadingXNotifChannel": "{} downloaden",
|
||||
"completeAppInstallationNotifChannel": "Voltooien van de app-installatie",
|
||||
"checkingForUpdatesNotifChannel": "Controleren op updates",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde en Track-Only apps controleren op updates",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "App verwijderen?",
|
||||
"other": "Apps verwijderen?"
|
||||
},
|
||||
"tooManyRequestsTryAgainInMinutes": {
|
||||
"one": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuut",
|
||||
"other": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuten"
|
||||
},
|
||||
"bgUpdateGotErrorRetryInMinutes": {
|
||||
"one": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuut",
|
||||
"other": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuten"
|
||||
},
|
||||
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||
"one": "Achtergrondupdatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig",
|
||||
"other": "Achtergrondupdatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig"
|
||||
},
|
||||
"apps": {
|
||||
"one": "{} app",
|
||||
"other": "{} apps"
|
||||
},
|
||||
"url": {
|
||||
"one": "{} URL",
|
||||
"other": "{} URLs"
|
||||
},
|
||||
"minute": {
|
||||
"one": "{} minuut",
|
||||
"other": "{} minuten"
|
||||
},
|
||||
"hour": {
|
||||
"one": "{} uur",
|
||||
"other": "{} uur"
|
||||
},
|
||||
"day": {
|
||||
"one": "{} dag",
|
||||
"other": "{} dagen"
|
||||
},
|
||||
"clearedNLogsBeforeXAfterY": {
|
||||
"one": "{n} logboekitem gewist (voor = {before}, na = {after})",
|
||||
"other": "{n} logboekitems gewist (voor = {before}, na = {after})"
|
||||
},
|
||||
"xAndNMoreUpdatesAvailable": {
|
||||
"one": "{} en nog 1 app hebben updates.",
|
||||
"other": "{} en {} meer apps hebben updates."
|
||||
},
|
||||
"xAndNMoreUpdatesInstalled": {
|
||||
"one": "{} en nog 1 app is bijgewerkt.",
|
||||
"other": "{} en {} meer apps zijn bijgewerkt."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} en nog 1 app zijn mogelijk bijgewerkt.",
|
||||
"other": "{} en {} meer apps zijn mogelijk bijgwerkt."
|
||||
}
|
||||
}
|
@ -28,8 +28,8 @@
|
||||
"xIsTrackOnly": "{} jest tylko obserwowane",
|
||||
"source": "Źródło",
|
||||
"app": "Aplikacja",
|
||||
"appsFromSourceAreTrackOnly": "Aplikacje z tego źródła są „tylko obserwowane”.",
|
||||
"youPickedTrackOnly": "Wybrano opcję „Tylko obserwuj”.",
|
||||
"appsFromSourceAreTrackOnly": "Aplikacje z tego źródła są tylko obserwowane.",
|
||||
"youPickedTrackOnly": "Wybrano opcję \"Tylko obserwuj\".",
|
||||
"trackOnlyAppDescription": "Aplikacja będzie obserwowana pod kątem aktualizacji, ale Obtainium nie będzie w stanie jej pobrać ani zainstalować.",
|
||||
"cancelled": "Anulowano",
|
||||
"appAlreadyAdded": "Aplikacja już została dodana",
|
||||
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Nie zainstalowano",
|
||||
"estimateInBrackets": "(Szacunkowo)",
|
||||
"selectAll": "Zaznacz wszystkie",
|
||||
"deselectN": "Odznacz {}",
|
||||
"deselectX": "Odznacz {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} zostanie usunięty z Obtainium, ale pozostanie zainstalowany na urządzeniu.",
|
||||
"removeSelectedAppsQuestion": "Usunąć wybrane aplikacje?",
|
||||
"removeSelectedApps": "Usuń wybrane aplikacje",
|
||||
@ -99,7 +99,7 @@
|
||||
"searchX": "Przeszukaj {}",
|
||||
"noResults": "Nie znaleziono wyników",
|
||||
"importX": "Importuj {}",
|
||||
"importedAppsIdDisclaimer": "Zaimportowane aplikacje mogą być wyświetlane jako „Niezainstalowane”.\nAby to naprawić, zainstaluj je ponownie za pomocą Obtainium.\nNie powinno to mieć wpływu na dane aplikacji.\n\nDotyczy tylko adresów URL i metod importu innych aplikacji.",
|
||||
"importedAppsIdDisclaimer": "Zaimportowane aplikacje mogą być wyświetlane jako niezainstalowane.\nAby to naprawić, przeinstaluj je za pomocą Obtainium.\nNie powinno to mieć wpływu na dane aplikacji.\n\nDotyczy tylko adresu URL i innych metod importu.",
|
||||
"importErrors": "Błędy importowania",
|
||||
"importedXOfYApps": "Zaimportowano {} z {} aplikacji.",
|
||||
"followingURLsHadErrors": "Następujące adresy URL zawierały błędy:",
|
||||
@ -218,12 +218,12 @@
|
||||
"autoApkFilterByArch": "Spróbuj filtrować pliki APK według architektury procesora, jeśli to możliwe",
|
||||
"overrideSource": "Nadpisz źródło",
|
||||
"dontShowAgain": "Nie pokazuj tego ponownie",
|
||||
"dontShowTrackOnlyWarnings": "Nie pokazuj ostrzeżeń „Tylko obserwowana”",
|
||||
"dontShowTrackOnlyWarnings": "Nie pokazuj ostrzeżeń \"Tylko obserwowana\"",
|
||||
"dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK",
|
||||
"moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji",
|
||||
"gitlabPATLabel": "Osobisty token dostępu GitLab\n(Umożliwia wyszukiwanie i lepsze wykrywanie APK)",
|
||||
"about": "Więcej informacji",
|
||||
"requiresCredentialsInSettings": "Wymaga to dodatkowych poświadczeń (w Ustawieniach)",
|
||||
"requiresCredentialsInSettings": "{}: Wymaga to dodatkowych poświadczeń (w Ustawieniach)",
|
||||
"checkOnStart": "Sprawdź aktualizacje przy uruchomieniu",
|
||||
"tryInferAppIdFromCode": "Spróbuj wywnioskować identyfikator aplikacji z kodu źródłowego",
|
||||
"removeOnExternalUninstall": "Automatyczne usuń odinstalowane zewnętrznie aplikacje",
|
||||
@ -239,7 +239,7 @@
|
||||
"sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków",
|
||||
"filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego",
|
||||
"customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")",
|
||||
"appsPossiblyUpdated": "Próbowano zaktualizować aplikację",
|
||||
"appsPossiblyUpdated": "Aplikacje mogły zostać zaktualizowane",
|
||||
"appsPossiblyUpdatedNotifDescription": "Powiadamia, gdy co najmniej jedna aktualizacja aplikacji została potencjalnie zastosowana w tle",
|
||||
"xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.",
|
||||
"enableBackgroundUpdates": "Włącz aktualizacje w tle",
|
||||
@ -256,6 +256,7 @@
|
||||
"highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe",
|
||||
"pickExportDir": "Wybierz katalog eksportu",
|
||||
"autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filtruj wersje według wyrażenia regularnego",
|
||||
"trySelectingSuggestedVersionCode": "Spróbuj wybierać sugerowany kod wersji APK",
|
||||
"dontSortReleasesList": "Utrzymaj kolejność wydań z interfejsu API",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "Pobieranie aplikacji",
|
||||
"completeAppInstallationNotifChannel": "Ukończenie instalacji aplikacji",
|
||||
"checkingForUpdatesNotifChannel": "Sprawdzanie dostępności aktualizacji",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Sprawdzaj tylko zainstalowane i obserwowane aplikacje pod kątem aktualizacji",
|
||||
"supportFixedAPKURL": "Obsługuj stałe adresy URL APK",
|
||||
"selectX": "Wybierz {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Usunąć aplikację?",
|
||||
"few": "Usunąć aplikacje?",
|
||||
|
@ -55,7 +55,7 @@
|
||||
"notInstalled": "Não Instalado",
|
||||
"estimateInBrackets": "(Aproximado)",
|
||||
"selectAll": "Selecionar All",
|
||||
"deselectN": "Deselecionar {}",
|
||||
"deselectX": "Deselecionar {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} sera removido do Obtainium mais permanecerá instalado no dispositivo.",
|
||||
"removeSelectedAppsQuestion": "Remover Apps Selecionados?",
|
||||
"removeSelectedApps": "Remover Apps Selecionados",
|
||||
@ -223,7 +223,7 @@
|
||||
"moveNonInstalledAppsToBottom": "Mover Apps não instalados para o fundo da visão de Apps",
|
||||
"gitlabPATLabel": "Token de Acceso Pessoal do Gitlab\n(Ativa Pesquisa e Melhor Descoberta de APKs)",
|
||||
"about": "Sobre",
|
||||
"requiresCredentialsInSettings": "Isso requer credenciais adicionais (em Configurações)",
|
||||
"requiresCredentialsInSettings": "{}: Isso requer credenciais adicionais (em Configurações)",
|
||||
"checkOnStart": "Checar por atualizações ao iniciar ",
|
||||
"tryInferAppIdFromCode": "Tente inferir o ID do App pelo código fonte",
|
||||
"removeOnExternalUninstall": "Remover automaticamente Apps desinstalados externamente",
|
||||
@ -256,6 +256,7 @@
|
||||
"highlightTouchTargets": "Destaque areas de toque menos óbvias",
|
||||
"pickExportDir": "Escolher Diretorio de Exportação",
|
||||
"autoExportOnChanges": "Auto-exportar em mudanças",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filtrar Versões por Expressão Regular",
|
||||
"trySelectingSuggestedVersionCode": "Tente selecionar a versão sugerida",
|
||||
"dontSortReleasesList": "Reter a ordem de lançamento da API",
|
||||
@ -263,9 +264,9 @@
|
||||
"debugMenu": "Menu Debug",
|
||||
"bgTaskStarted": "Tarefa em segundo plano iniciada - verifique os logs.",
|
||||
"runBgCheckNow": "Execute a verificação de atualização em segundo plano agora",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"versionExtractWholePage": "Aplicar Regex de Extração de Versão à Página Inteira",
|
||||
"installing": "Instalando",
|
||||
"skipUpdateNotifications": "Pular notificações de update",
|
||||
"updatesAvailableNotifChannel": "Atualizações Disponíveis",
|
||||
"appsUpdatedNotifChannel": "Apps Atualizados",
|
||||
"appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de Apps",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "Baixando {}",
|
||||
"completeAppInstallationNotifChannel": "Instalação completa do App",
|
||||
"checkingForUpdatesNotifChannel": "Checando por Atualizações",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Remover App?",
|
||||
"other": "Remover Apps?"
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"invalidURLForSource": "Неверный URL-адрес {} приложения",
|
||||
"invalidURLForSource": "Неверный URL-адрес приложения: {}",
|
||||
"noReleaseFound": "Не удалось найти подходящий релиз",
|
||||
"noVersionFound": "Не удалось определить версию релиза",
|
||||
"urlMatchesNoSource": "URL-адрес не соответствует известному источнику",
|
||||
@ -9,41 +9,41 @@
|
||||
"placeholder": "Заполнитель",
|
||||
"someErrors": "Возникли некоторые ошибки",
|
||||
"unexpectedError": "Неожиданная ошибка",
|
||||
"ok": "Окей",
|
||||
"ok": "Ok",
|
||||
"and": "и",
|
||||
"githubPATLabel": "Персональный токен доступа GitHub (увеличивает лимит запросов)",
|
||||
"githubPATLabel": "Персональный токен доступа GitHub\n(увеличивает лимит запросов)",
|
||||
"includePrereleases": "Включить предварительные релизы",
|
||||
"fallbackToOlderReleases": "Откатиться к более старым версиям",
|
||||
"filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов\nс помощью регулярного выражения",
|
||||
"fallbackToOlderReleases": "Откатываться к предыдущей версии",
|
||||
"filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов\n(регулярное выражение)",
|
||||
"invalidRegEx": "Неверное регулярное выражение",
|
||||
"noDescription": "Нет описания",
|
||||
"cancel": "Отмена",
|
||||
"continue": "Продолжить",
|
||||
"requiredInBrackets": "(Обязательно)",
|
||||
"dropdownNoOptsError": "Ошибка: Выпадающий список должен содержать хотя бы одну опцию",
|
||||
"requiredInBrackets": "(обязательно)",
|
||||
"dropdownNoOptsError": "Ошибка: в выпадающем списке должна быть выбрана хотя бы одна настройка",
|
||||
"colour": "Цвет",
|
||||
"githubStarredRepos": "Помеченные звездочкой репозитории на GitHub",
|
||||
"githubStarredRepos": "Избранные репозитории GitHub",
|
||||
"uname": "Имя пользователя",
|
||||
"wrongArgNum": "Неправильное количество предоставленных аргументов",
|
||||
"xIsTrackOnly": "{} только для отслеживания",
|
||||
"source": "Источник",
|
||||
"app": "Приложение",
|
||||
"appsFromSourceAreTrackOnly": "Приложения из этого источника являются 'только для отслеживания'.",
|
||||
"youPickedTrackOnly": "Вы выбрали опцию 'Только для отслеживания'.",
|
||||
"trackOnlyAppDescription": "Приложение будет отслеживаться на предмет обновлений, но Obtainium не сможет загрузить или установить его.",
|
||||
"appsFromSourceAreTrackOnly": "Приложения из этого источника настроены только для отслеживания",
|
||||
"youPickedTrackOnly": "Вы выбрали опцию 'Только для отслеживания'",
|
||||
"trackOnlyAppDescription": "Приложение будет отслеживаться на предмет обновлений, но Obtainium не сможет загрузить или установить его",
|
||||
"cancelled": "Отменено",
|
||||
"appAlreadyAdded": "Приложение уже добавлено",
|
||||
"alreadyUpToDateQuestion": "Приложение уже обновлено?",
|
||||
"addApp": "Добавить приложение",
|
||||
"addApp": "Добавить",
|
||||
"appSourceURL": "URL-источник приложения",
|
||||
"error": "Ошибка",
|
||||
"add": "Добавить",
|
||||
"searchSomeSourcesLabel": "Поиск (только в некоторых источниках)",
|
||||
"searchSomeSourcesLabel": "Поиск (в некоторых источниках)",
|
||||
"search": "Поиск",
|
||||
"additionalOptsFor": "Дополнительные опции для {}",
|
||||
"additionalOptsFor": "Дополнительные настройки для {}",
|
||||
"supportedSources": "Поддерживаемые источники",
|
||||
"trackOnlyInBrackets": "(Только для отслеживания)",
|
||||
"searchableInBrackets": "(Поиск)",
|
||||
"trackOnlyInBrackets": "(только отслеживание)",
|
||||
"searchableInBrackets": "(поиск)",
|
||||
"appsString": "Приложения",
|
||||
"noApps": "Нет приложений",
|
||||
"noAppsForFilter": "Нет приложений для фильтра",
|
||||
@ -54,9 +54,9 @@
|
||||
"estimateInBracketsShort": "(Оценка)",
|
||||
"notInstalled": "Не установлено",
|
||||
"estimateInBrackets": "(Оценка)",
|
||||
"selectAll": "Выбрать все",
|
||||
"deselectN": "Отменить выбор {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется установленным на устройстве.",
|
||||
"selectAll": "Выбрать всё",
|
||||
"deselectX": "Отменить выбор {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется на устройстве",
|
||||
"removeSelectedAppsQuestion": "Удалить выбранные приложения?",
|
||||
"removeSelectedApps": "Удалить выбранные приложения",
|
||||
"updateX": "Обновить {}",
|
||||
@ -65,17 +65,17 @@
|
||||
"changeX": "Изменить {}",
|
||||
"installUpdateApps": "Установить/Обновить приложения",
|
||||
"installUpdateSelectedApps": "Установить/Обновить выбранные приложения",
|
||||
"markXSelectedAppsAsUpdated": "Отметить {} выбранные приложения как обновленные?",
|
||||
"markXSelectedAppsAsUpdated": "Выбрано приложений: {}. Отметить как обновлённые?",
|
||||
"no": "Нет",
|
||||
"yes": "Да",
|
||||
"markSelectedAppsUpdated": "Отметить выбранные приложения как обновленные",
|
||||
"markSelectedAppsUpdated": "Отметить выбранные приложения как обновлённые",
|
||||
"pinToTop": "Закрепить сверху",
|
||||
"unpinFromTop": "Открепить",
|
||||
"resetInstallStatusForSelectedAppsQuestion": "Сбросить статус установки для выбранных приложений?",
|
||||
"installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, неправильная из-за неудачных обновлений или других проблем.",
|
||||
"installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, некорректная — из-за неудачных обновлений или других проблем",
|
||||
"shareSelectedAppURLs": "Поделиться выбранными URL-адресами приложений",
|
||||
"resetInstallStatus": "Сбросить статус установки",
|
||||
"more": "Еще",
|
||||
"more": "Ещё",
|
||||
"removeOutdatedFilter": "Удалить фильтр для устаревших приложений",
|
||||
"showOutdatedOnly": "Показывать только устаревшие приложения",
|
||||
"filter": "Фильтр",
|
||||
@ -85,7 +85,7 @@
|
||||
"author": "Автор",
|
||||
"upToDateApps": "Приложения со свежими обновлениями",
|
||||
"nonInstalledApps": "Неустановленные приложения",
|
||||
"importExport": "Импорт/экспорт",
|
||||
"importExport": "Данные",
|
||||
"settings": "Настройки",
|
||||
"exportedTo": "Экспортировано в {}",
|
||||
"obtainiumExport": "Экспорт из Obtainium",
|
||||
@ -99,63 +99,63 @@
|
||||
"searchX": "Поиск {}",
|
||||
"noResults": "Результатов не найдено",
|
||||
"importX": "Импорт {}",
|
||||
"importedAppsIdDisclaimer": "Импортированные приложения могут неверно отображаться как 'Не установлены'.\nДля исправления этой проблемы повторно установите их через Obtainium.\nЭто не должно повлиять на данные приложения.\n\nПроблемы возникают только при импорте из URL-адреса и сторонних источников.",
|
||||
"importedAppsIdDisclaimer": "Импортированные приложения могут неверно отображаться как неустановленные.\nДля исправления этой проблемы повторно установите их через Obtainium.\nЭто не должно повлиять на данные приложения.\n\nПроблемы возникают только при импорте из URL-адреса и сторонних источников",
|
||||
"importErrors": "Ошибка импорта",
|
||||
"importedXOfYApps": "Импортировано {} из {} приложений.",
|
||||
"importedXOfYApps": "Импортировано приложений: {} из {}",
|
||||
"followingURLsHadErrors": "При импорте следующие URL-адреса содержали ошибки:",
|
||||
"okay": "Окей",
|
||||
"okay": "Ok",
|
||||
"selectURL": "Выбрать URL-адрес",
|
||||
"selectURLs": "Выбрать URL-адреса",
|
||||
"pick": "Выбрать",
|
||||
"theme": "Тема",
|
||||
"dark": "Темная",
|
||||
"dark": "Тёмная",
|
||||
"light": "Светлая",
|
||||
"followSystem": "Как в системе",
|
||||
"followSystem": "Системная",
|
||||
"obtainium": "Obtainium",
|
||||
"materialYou": "Material You",
|
||||
"useBlackTheme": "Использовать чёрную тему",
|
||||
"appSortBy": "Сортировка приложений по",
|
||||
"appSortBy": "Сортировка приложений",
|
||||
"authorName": "Автор/Название",
|
||||
"nameAuthor": "Название/Автор",
|
||||
"asAdded": "В порядке добавления",
|
||||
"appSortOrder": "Порядок сортировки приложений",
|
||||
"appSortOrder": "Порядок",
|
||||
"ascending": "По возрастанию",
|
||||
"descending": "По убыванию",
|
||||
"bgUpdateCheckInterval": "Интервал проверки обновлений в фоновом режиме",
|
||||
"neverManualOnly": "Никогда - Только вручную",
|
||||
"neverManualOnly": "Никогда — только вручную",
|
||||
"appearance": "Внешний вид",
|
||||
"showWebInAppView": "Показывать исходную веб-страницу в представлении приложения",
|
||||
"pinUpdates": "Закрепить обновления сверху списка приложений",
|
||||
"showWebInAppView": "Показывать исходную веб-страницу на странице приложения",
|
||||
"pinUpdates": "Отображать обновления приложений сверху списка",
|
||||
"updates": "Обновления",
|
||||
"sourceSpecific": "Специфика источника",
|
||||
"appSource": "Источник приложения",
|
||||
"sourceSpecific": "Настройки источников",
|
||||
"appSource": "Исходный код",
|
||||
"noLogs": "Нет журналов",
|
||||
"appLogs": "Журналы приложений",
|
||||
"appLogs": "Логи",
|
||||
"close": "Закрыть",
|
||||
"share": "Поделиться",
|
||||
"appNotFound": "Приложение не найдено",
|
||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||
"pickAnAPK": "Выберите APK-файл",
|
||||
"appHasMoreThanOnePackage": "{} имеет более одного пакета:",
|
||||
"deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}.",
|
||||
"deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}",
|
||||
"deviceSupportsFollowingArchs": "Ваше устройство поддерживает следующие архитектуры процессора:",
|
||||
"warning": "Предупреждение",
|
||||
"sourceIsXButPackageFromYPrompt": "Источник приложения - '{}', но пакет для установки получен из '{}'. Продолжить?",
|
||||
"sourceIsXButPackageFromYPrompt": "Источник приложения — '{}', но пакет для установки получен из '{}'. Продолжить?",
|
||||
"updatesAvailable": "Доступны обновления",
|
||||
"updatesAvailableNotifDescription": "Уведомляет пользователя о наличии обновлений для одного или нескольких приложений, отслеживаемых Obtainium",
|
||||
"noNewUpdates": "Нет новых обновлений.",
|
||||
"xHasAnUpdate": "{} есть обновление.",
|
||||
"updatesAvailableNotifDescription": "Уведомляет о наличии обновлений для одного или нескольких приложений в Obtainium",
|
||||
"noNewUpdates": "Нет новых обновлений",
|
||||
"xHasAnUpdate": "{} есть обновление",
|
||||
"appsUpdated": "Приложения обновлены",
|
||||
"appsUpdatedNotifDescription": "Уведомляет пользователя о том, что обновления для одного или нескольких приложений были применены в фоновом режиме",
|
||||
"xWasUpdatedToY": "{} была обновлена до версии {}.",
|
||||
"appsUpdatedNotifDescription": "Уведомляет об обновлении одного или нескольких приложений в фоновом режиме",
|
||||
"xWasUpdatedToY": "{} была обновлена до версии {}",
|
||||
"errorCheckingUpdates": "Ошибка при проверке обновлений",
|
||||
"errorCheckingUpdatesNotifDescription": "Уведомление, которое появляется, когда проверка обновлений в фоновом режиме завершилась с ошибкой",
|
||||
"errorCheckingUpdatesNotifDescription": "Уведомление о завершении проверки обновлений в фоновом режиме с ошибкой",
|
||||
"appsRemoved": "Приложение удалено",
|
||||
"appsRemovedNotifDescription": "Уведомляет пользователя о том, что одно или несколько приложений было удалено из-за ошибок при их загрузке",
|
||||
"appsRemovedNotifDescription": "Уведомление об удалении одного или несколько приложений из-за ошибок при их загрузке",
|
||||
"xWasRemovedDueToErrorY": "{} был удален из-за ошибки: {}",
|
||||
"completeAppInstallation": "Завершение установки приложения",
|
||||
"obtainiumMustBeOpenToInstallApps": "Для установки приложений Obtainium должен быть открыт",
|
||||
"completeAppInstallationNotifDescription": "Просит пользователя вернуться в Obtainium, чтобы завершить установку приложения",
|
||||
"obtainiumMustBeOpenToInstallApps": "Obtainium должен быть открыт для установки приложений",
|
||||
"completeAppInstallationNotifDescription": "Уведомление о необходимости открыть Obtainium для завершения установки приложения",
|
||||
"checkingForUpdates": "Проверка обновлений",
|
||||
"checkingForUpdatesNotifDescription": "Временное уведомление, которое появляется при проверке обновлений",
|
||||
"pleaseAllowInstallPerm": "Пожалуйста, разрешите Obtainium устанавливать приложения",
|
||||
@ -167,14 +167,14 @@
|
||||
"never": "Никогда",
|
||||
"latestVersionX": "Последняя версия: {}",
|
||||
"installedVersionX": "Установленная версия: {}",
|
||||
"lastUpdateCheckX": "Последняя проверка обновлений: {}",
|
||||
"lastUpdateCheckX": "Последняя проверка: {}",
|
||||
"remove": "Удалить",
|
||||
"yesMarkUpdated": "Да, отметить как обновленное",
|
||||
"fdroid": "Официальный F-Droid",
|
||||
"fdroid": "Официальные репозитории F-Droid",
|
||||
"appIdOrName": "ID или название приложения",
|
||||
"appId": "ID приложения",
|
||||
"appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено",
|
||||
"reposHaveMultipleApps": "В хранилище может быть несколько приложений",
|
||||
"reposHaveMultipleApps": "В хранилище несколько приложений",
|
||||
"fdroidThirdPartyRepo": "Сторонние репозитории F-Droid",
|
||||
"steam": "Steam",
|
||||
"steamMobile": "Steam Mobile",
|
||||
@ -182,90 +182,91 @@
|
||||
"install": "Установить",
|
||||
"markInstalled": "Пометить как установленное",
|
||||
"update": "Обновить",
|
||||
"markUpdated": "Отметить обновленным",
|
||||
"additionalOptions": "Дополнительные опции",
|
||||
"markUpdated": "Отметить обновлённым",
|
||||
"additionalOptions": "Дополнительные настройки",
|
||||
"disableVersionDetection": "Отключить обнаружение версии",
|
||||
"noVersionDetectionExplanation": "Эта опция должна использоваться только для приложений, где обнаружение версии не работает корректно.",
|
||||
"noVersionDetectionExplanation": "Эта настройка должна использоваться только для приложений, где обнаружение версии не работает корректно",
|
||||
"downloadingX": "Загрузка {}",
|
||||
"downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения",
|
||||
"noAPKFound": "APK не найден",
|
||||
"noVersionDetection": "Версий не обнаружено",
|
||||
"noVersionDetection": "Обнаружение версий отключено",
|
||||
"categorize": "Категоризировать",
|
||||
"categories": "Категории",
|
||||
"category": "Категория",
|
||||
"noCategory": "Без категории",
|
||||
"noCategories": "Без категорий",
|
||||
"deleteCategoriesQuestion": "Удалить категории?",
|
||||
"categoryDeleteWarning": "Все приложения в удаленных категориях будут помечены как без категории.",
|
||||
"categoryDeleteWarning": "Все приложения в удаленных категориях будут помечены как без категории",
|
||||
"addCategory": "Добавить категорию",
|
||||
"label": "Метка",
|
||||
"language": "Язык",
|
||||
"copiedToClipboard": "Скопировано в буфер обмена",
|
||||
"storagePermissionDenied": "Отказано в доступе к хранилищу",
|
||||
"selectedCategorizeWarning": "Это заменит все текущие настройки категорий для выбранных приложений.",
|
||||
"filterAPKsByRegEx": "Фильтровать APK-файлы с помощью\nрегулярного выражения",
|
||||
"selectedCategorizeWarning": "Это заменит все текущие настройки категорий для выбранных приложений",
|
||||
"filterAPKsByRegEx": "Отфильтровать APK-файлы\n(регулярное выражение)",
|
||||
"removeFromObtainium": "Удалить из Obtainium",
|
||||
"uninstallFromDevice": "Удалить с устройства",
|
||||
"onlyWorksWithNonVersionDetectApps": "Работает только для приложений с отключенным определением версии.",
|
||||
"releaseDateAsVersion": "Использовать дату выпуска в качестве версии",
|
||||
"releaseDateAsVersionExplanation": "Этот параметр следует использовать только для приложений, в которых определение версии не работает правильно, но имеется дата выпуска.",
|
||||
"onlyWorksWithNonVersionDetectApps": "Работает только для приложений с отключенным определением версии",
|
||||
"releaseDateAsVersion": "Дата выпуска вместо версии",
|
||||
"releaseDateAsVersionExplanation": "Этот параметр следует использовать только для приложений, в которых определение версии не работает правильно, но имеется дата выпуска",
|
||||
"changes": "Изменения",
|
||||
"releaseDate": "Дата выпуска",
|
||||
"importFromURLsInFile": "Импорт URL-адресов из файла (например, OPML)",
|
||||
"importFromURLsInFile": "Импорт из файла URL-адресов (например: OPML)",
|
||||
"versionDetection": "Определение версии",
|
||||
"standardVersionDetection": "Стандартное определение версии",
|
||||
"standardVersionDetection": "Стандартное",
|
||||
"groupByCategory": "Группировать по категориям",
|
||||
"autoApkFilterByArch": "Попытка фильтрации APK-файлов по архитектуре процессора, если это возможно",
|
||||
"autoApkFilterByArch": "Попытаться отфильтровать APK-файлы по архитектуре процессора",
|
||||
"overrideSource": "Переопределить источник",
|
||||
"dontShowAgain": "Не показывать снова",
|
||||
"dontShowTrackOnlyWarnings": "Не показывать предупреждения о только отслеживаемых приложениях",
|
||||
"dontShowAPKOriginWarnings": "Не показывать предупреждения об источнике APK-файлов",
|
||||
"moveNonInstalledAppsToBottom": "Переместить неустановленные приложения вниз списка",
|
||||
"gitlabPATLabel": "Персональный токен доступа GitLab\n(Включает поиск и улучшает обнаружение APK)",
|
||||
"about": "О приложении",
|
||||
"requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)",
|
||||
"dontShowAPKOriginWarnings": "Не показывать предупреждения об отличающемся источнике APK-файлов",
|
||||
"moveNonInstalledAppsToBottom": "Отображать неустановленные приложения внизу списка",
|
||||
"gitlabPATLabel": "Персональный токен доступа GitLab\n(включает поиск и улучшает обнаружение APK)",
|
||||
"about": "Описание",
|
||||
"requiresCredentialsInSettings": "{}: Для этого требуются дополнительные учетные данные (в настройках)",
|
||||
"checkOnStart": "Проверять наличие обновлений при запуске",
|
||||
"tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода",
|
||||
"removeOnExternalUninstall": "Автоматически убирать из списка удаленные извне приложения",
|
||||
"pickHighestVersionCode": "Автовыбор кода наивысшей версии APK",
|
||||
"checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения",
|
||||
"pickHighestVersionCode": "Автовыбор актуальной версии кода APK",
|
||||
"checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы приложения",
|
||||
"disablePageTransitions": "Отключить анимацию перехода между страницами",
|
||||
"reversePageTransitions": "Реверс анимации перехода между страницами",
|
||||
"minStarCount": "Минимальное количество звёзд",
|
||||
"addInfoBelow": "Добавьте эту информацию ниже.",
|
||||
"addInfoInSettings": "Добавьте эту информацию в Настройки.",
|
||||
"githubSourceNote": "Лимит запросов GitHub можно обойти, используя ключ API.",
|
||||
"gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.",
|
||||
"sortByFileNamesNotLinks": "Сортировать по именам файлов, а не по полным ссылкам",
|
||||
"filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску по регулярному выражению",
|
||||
"customLinkFilterRegex": "Пользовательский фильтр ссылок APK по регулярному выражению (по умолчанию '.apk$')",
|
||||
"addInfoBelow": "Добавьте эту информацию ниже",
|
||||
"addInfoInSettings": "Добавьте эту информацию в Настройки",
|
||||
"githubSourceNote": "Используя ключ API можно обойти лимит запросов GitHub",
|
||||
"gitlabSourceNote": "Без ключа API может не работать извлечение APK с GitLab",
|
||||
"sortByFileNamesNotLinks": "Сортировать по именам файлов, а не ссылкам целиком",
|
||||
"filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску\n(регулярное выражение)",
|
||||
"customLinkFilterRegex": "Пользовательский фильтр ссылок APK\n(регулярное выражение, по умолчанию: '.apk$')",
|
||||
"appsPossiblyUpdated": "Попытки обновления приложений",
|
||||
"appsPossiblyUpdatedNotifDescription": "Уведомляет пользователя о возможных обновлениях одного или нескольких приложений в фоновом режиме",
|
||||
"xWasPossiblyUpdatedToY": "{} возможно был обновлен до {}.",
|
||||
"appsPossiblyUpdatedNotifDescription": "Уведомление о возможных обновлениях одного или нескольких приложений в фоновом режиме",
|
||||
"xWasPossiblyUpdatedToY": "{} возможно был обновлен до {}",
|
||||
"enableBackgroundUpdates": "Включить обновления в фоне",
|
||||
"backgroundUpdateReqsExplanation": "Фоновые обновления могут быть невозможны для всех приложений.",
|
||||
"backgroundUpdateLimitsExplanation": "Успех фоновой установки можно определить только после открытия Obtainium.",
|
||||
"verifyLatestTag": "Проверьте тег 'последний'",
|
||||
"intermediateLinkRegex": "Фильтр ссылок 'промежуточного' типа для приоритетного посещения",
|
||||
"backgroundUpdateReqsExplanation": "Фоновые обновления могут быть возможны не для всех приложений",
|
||||
"backgroundUpdateLimitsExplanation": "Успешность фоновой установки можно определить только после открытия Obtainium",
|
||||
"verifyLatestTag": "Проверять тег 'latest'",
|
||||
"intermediateLinkRegex": "Фильтр промежуточных ссылок для первоочередного посещения\n(регулярное выражение)",
|
||||
"intermediateLinkNotFound": "Промежуточная ссылка не найдена",
|
||||
"exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)",
|
||||
"bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi",
|
||||
"autoSelectHighestVersionCode": "Автоматически выбирать APK с наивысшим кодом версии",
|
||||
"autoSelectHighestVersionCode": "Автоматически выбирать APK с актуальной версией кода",
|
||||
"versionExtractionRegEx": "Регулярное выражение для извлечения версии",
|
||||
"matchGroupToUse": "Выберите группу для использования",
|
||||
"highlightTouchTargets": "Выделить менее очевидные элементы управления касанием",
|
||||
"pickExportDir": "Выбрать каталог для экспорта",
|
||||
"autoExportOnChanges": "Автоэкспорт при изменениях",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Фильтровать версии по регулярному выражению",
|
||||
"trySelectingSuggestedVersionCode": "Попробуйте выбрать предложенный код версии APK",
|
||||
"dontSortReleasesList": "Сохранить порядок выпусков от API",
|
||||
"dontSortReleasesList": "Сохранить порядок релизов от API",
|
||||
"reverseSort": "Обратная сортировка",
|
||||
"debugMenu": "Меню Отладки",
|
||||
"bgTaskStarted": "Фоновая задача начата - проверьте журналы.",
|
||||
"debugMenu": "Меню отладки",
|
||||
"bgTaskStarted": "Фоновая задача начата — проверьте журналы",
|
||||
"runBgCheckNow": "Запустить проверку фонового обновления сейчас",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"versionExtractWholePage": "Применить регулярное выражение версии ко всей странице",
|
||||
"installing": "Устанавливается",
|
||||
"skipUpdateNotifications": "Не оповещать об обновлениях",
|
||||
"updatesAvailableNotifChannel": "Доступны обновления",
|
||||
"appsUpdatedNotifChannel": "Приложения обновлены",
|
||||
"appsPossiblyUpdatedNotifChannel": "Попытки обновления приложений",
|
||||
@ -274,56 +275,59 @@
|
||||
"downloadingXNotifChannel": "Загрузка {}",
|
||||
"completeAppInstallationNotifChannel": "Завершение установки приложения",
|
||||
"checkingForUpdatesNotifChannel": "Проверка обновлений",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Удалить приложение?",
|
||||
"other": "Удалить приложения?"
|
||||
},
|
||||
"tooManyRequestsTryAgainInMinutes": {
|
||||
"one": "Слишком много запросов (ограничение скорости) - попробуйте снова через {} минуту",
|
||||
"other": "Слишком много запросов (ограничение скорости) - попробуйте снова через {} минуты"
|
||||
"one": "Слишком много запросов (ограничение скорости) — попробуйте снова через {} минуту",
|
||||
"other": "Слишком много запросов (ограничение скорости) — попробуйте снова через {} минуты"
|
||||
},
|
||||
"bgUpdateGotErrorRetryInMinutes": {
|
||||
"one": "При проверке обновлений в фоновом режиме возникла ошибка {}, повторная проверка будет запланирована через {} минуту",
|
||||
"other": "При проверке обновлений в фоновом режиме возникла ошибка {}, повторная проверка будет запланирована через {} минуты"
|
||||
},
|
||||
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||
"one": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновление - Пользователю будет отправлено уведомление, если это необходимо",
|
||||
"other": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновлений - Пользователю будет отправлено уведомление, если это необходимо"
|
||||
"one": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновление — Пользователю будет отправлено уведомление, если это необходимо",
|
||||
"other": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновлений — Пользователю будет отправлено уведомление, если это необходимо"
|
||||
},
|
||||
"apps": {
|
||||
"one": "{} Приложение",
|
||||
"other": "{} Приложений"
|
||||
"one": "{} приложение",
|
||||
"other": "{} приложений"
|
||||
},
|
||||
"url": {
|
||||
"one": "{} URL-адрес",
|
||||
"other": "{} URL-адреса"
|
||||
},
|
||||
"minute": {
|
||||
"one": "{} Минута",
|
||||
"other": "{} Минуты"
|
||||
"one": "{} минута",
|
||||
"other": "{} минуты"
|
||||
},
|
||||
"hour": {
|
||||
"one": "{} Час",
|
||||
"other": "{} Часов"
|
||||
"one": "{} час",
|
||||
"other": "{} часов"
|
||||
},
|
||||
"day": {
|
||||
"one": "{} День",
|
||||
"other": "{} Дней"
|
||||
"one": "{} день",
|
||||
"other": "{} дней"
|
||||
},
|
||||
"clearedNLogsBeforeXAfterY": {
|
||||
"one": "Очищен {n} журнал (до = {before}, после = {after})",
|
||||
"other": "Очищено {n} журналов (до = {before}, после = {after})"
|
||||
},
|
||||
"xAndNMoreUpdatesAvailable": {
|
||||
"one": "У {} и еще 1 приложения есть обновление.",
|
||||
"other": "У {} и ещё {} приложений есть обновления."
|
||||
"one": "У {} и еще 1 приложения есть обновление",
|
||||
"other": "У {} и ещё {} приложений есть обновления"
|
||||
},
|
||||
"xAndNMoreUpdatesInstalled": {
|
||||
"one": "{} и ещё 1 приложение были обновлены.",
|
||||
"other": "{} и ещё {} приложений были обновлены."
|
||||
"one": "{} и ещё 1 приложение были обновлены",
|
||||
"other": "{} и ещё {} приложений были обновлены"
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} и ещё 1 приложение могли быть обновлены.",
|
||||
"other": "{} и ещё {} приложений могли быть обновлены."
|
||||
"one": "{} и ещё 1 приложение могли быть обновлены",
|
||||
"other": "{} и ещё {} приложений могли быть обновлены"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
319
assets/translations/sv.json
Normal file
319
assets/translations/sv.json
Normal file
@ -0,0 +1,319 @@
|
||||
{
|
||||
"invalidURLForSource": "Inte giltig {} App-URL",
|
||||
"noReleaseFound": "Kunde inte hitta en lämplig releaseversion",
|
||||
"noVersionFound": "Kunde inte bestämma releaseversion",
|
||||
"urlMatchesNoSource": "URL matchar inte känd källa",
|
||||
"cantInstallOlderVersion": "Kan inte installera en äldre version av en app",
|
||||
"appIdMismatch": "Nerladdat paket-ID matchar inte nuvarande App-ID",
|
||||
"functionNotImplemented": "This class has not implemented this function",
|
||||
"placeholder": "Platshållare",
|
||||
"someErrors": "Några fel uppstod",
|
||||
"unexpectedError": "Oväntat fel",
|
||||
"ok": "Okej",
|
||||
"and": "och",
|
||||
"githubPATLabel": "GitHub Personal Access Token (Increases Rate Limit)",
|
||||
"includePrereleases": "Inkludera förreleaser",
|
||||
"fallbackToOlderReleases": "Fall tillbaka till äldre releaser",
|
||||
"filterReleaseTitlesByRegEx": "Filter Release Titles by Regular Expression",
|
||||
"invalidRegEx": "Invalid regular expression",
|
||||
"noDescription": "Ingen beskrivning",
|
||||
"cancel": "Avbryt",
|
||||
"continue": "Fortsätt",
|
||||
"requiredInBrackets": "(Kräver)",
|
||||
"dropdownNoOptsError": "ERROR: DROPDOWN MUST HAVE AT LEAST ONE OPT",
|
||||
"colour": "Färg",
|
||||
"githubStarredRepos": "GitHub Stjärnmärkta Förråd",
|
||||
"uname": "Användarnamn",
|
||||
"wrongArgNum": "Wrong number of arguments provided",
|
||||
"xIsTrackOnly": "{} är 'Följ-Endast'",
|
||||
"source": "Källa",
|
||||
"app": "App",
|
||||
"appsFromSourceAreTrackOnly": "Apparna från denna källa är 'Följ-Endast'.",
|
||||
"youPickedTrackOnly": "Du har markerat 'Följ-Endast'-alternativet",
|
||||
"trackOnlyAppDescription": "Appen kommer följas för uppdateringar men Obtainium kommer inte ladda ner eller installera den.",
|
||||
"cancelled": "Avbruten",
|
||||
"appAlreadyAdded": "App redan tillagd",
|
||||
"alreadyUpToDateQuestion": "App redan uppdaterad?",
|
||||
"addApp": "Lägg till App",
|
||||
"appSourceURL": "URL till Appkälla",
|
||||
"error": "Fel",
|
||||
"add": "Lägg till",
|
||||
"searchSomeSourcesLabel": "Sök (Bara några källor)",
|
||||
"search": "Sök",
|
||||
"additionalOptsFor": "Ytterligare Alternativ för {}",
|
||||
"supportedSources": "Stödda Källor",
|
||||
"trackOnlyInBrackets": "(Följ-Endast)",
|
||||
"searchableInBrackets": "(Sökbar)",
|
||||
"appsString": "Appar",
|
||||
"noApps": "Inga Appar",
|
||||
"noAppsForFilter": "Inga Appar för Filter",
|
||||
"byX": "Av {}",
|
||||
"percentProgress": "Progress: {}%",
|
||||
"pleaseWait": "Vänta",
|
||||
"updateAvailable": "Uppdatering Tillgänglig",
|
||||
"estimateInBracketsShort": "(Est.)",
|
||||
"notInstalled": "Inte Installerad",
|
||||
"estimateInBrackets": "(Uppskattning)",
|
||||
"selectAll": "Välj Alla",
|
||||
"deselectX": "Avmarkera {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} kommer tas bort från Obtainium men kommer vara fortsatt installerad på enheten.",
|
||||
"removeSelectedAppsQuestion": "Ta bort markerade Appar?",
|
||||
"removeSelectedApps": "Ta bort markerade Appar",
|
||||
"updateX": "Uppdatera {}",
|
||||
"installX": "Installera {}",
|
||||
"markXTrackOnlyAsUpdated": "Märk {}\n(Följ-Endast)\nsom Uppdaterad",
|
||||
"changeX": "Byt {}",
|
||||
"installUpdateApps": "Installera/Uppdatera Appar",
|
||||
"installUpdateSelectedApps": "Installera/Uppdatera Markerade Appar",
|
||||
"markXSelectedAppsAsUpdated": "Märk {} markerade Appar som Uppdaterade?",
|
||||
"no": "Nej",
|
||||
"yes": "Ja",
|
||||
"markSelectedAppsUpdated": "Märk Valda Appar som Uppdaterade",
|
||||
"pinToTop": "Nåla fast högst upp",
|
||||
"unpinFromTop": "Avnåla",
|
||||
"resetInstallStatusForSelectedAppsQuestion": "Återställ Installationsstatus för valda Appar?",
|
||||
"installStatusOfXWillBeResetExplanation": "Installationsstatusen för de markerade apparna kommer återställas.\n\n Detta kan hjälpa när appversionen visad i Obtanium är fel på grund av misslyckade uppdateringar eller andra orsaker.",
|
||||
"shareSelectedAppURLs": "Dela Valda Appars URL:er",
|
||||
"resetInstallStatus": "Återställ Installationstatus",
|
||||
"more": "Mer",
|
||||
"removeOutdatedFilter": "Ta bort Utgånga App-filtret",
|
||||
"showOutdatedOnly": "Visa Endast Utgånga Appar",
|
||||
"filter": "Filter",
|
||||
"filterActive": "Filter *",
|
||||
"filterApps": "Filtrera Appar",
|
||||
"appName": "Appnamn",
|
||||
"author": "Utvecklare",
|
||||
"upToDateApps": "Uppdaterade Appar",
|
||||
"nonInstalledApps": "Icke-Installerade Appar",
|
||||
"importExport": "Importera/Exportera",
|
||||
"settings": "Inställningar",
|
||||
"exportedTo": "Exporterad till {}",
|
||||
"obtainiumExport": "Obtainiumexport",
|
||||
"invalidInput": "Ogiltig inmatning",
|
||||
"importedX": "Importerad {}",
|
||||
"obtainiumImport": "Obtainium Import",
|
||||
"importFromURLList": "Importera från URL-lista",
|
||||
"searchQuery": "Sökförfrågan",
|
||||
"appURLList": "App URL List",
|
||||
"line": "Linje",
|
||||
"searchX": "Sök {}",
|
||||
"noResults": "Inga resultat",
|
||||
"importX": "Importera {}",
|
||||
"importedAppsIdDisclaimer": "Importerade Appar kan felaktigt visas som \"Inte Installerad\".\nFör att fixa detta återinstallera dem genom Obtainium.\nDetta skall inte påverka appdata.\n\n Påverkar endast URL:en och tredjepartsimportermetoder.",
|
||||
"importErrors": "Importfel",
|
||||
"importedXOfYApps": "{} av {} Appar importerade.",
|
||||
"followingURLsHadErrors": "Följande URL:er hade fel:",
|
||||
"okay": "Okej",
|
||||
"selectURL": "Välj URL",
|
||||
"selectURLs": "Välj URL:er",
|
||||
"pick": "Välj",
|
||||
"theme": "Tema",
|
||||
"dark": "Mörkt",
|
||||
"light": "Ljust",
|
||||
"followSystem": "Följ System",
|
||||
"obtainium": "Obtainium",
|
||||
"materialYou": "Material You",
|
||||
"useBlackTheme": "Använd svart tema",
|
||||
"appSortBy": "Sortera Appar via",
|
||||
"authorName": "Utvecklare/Namn",
|
||||
"nameAuthor": "Namn/Utvecklare",
|
||||
"asAdded": "As Added",
|
||||
"appSortOrder": "App Sort Order",
|
||||
"ascending": "Stigande",
|
||||
"descending": "Fallande",
|
||||
"bgUpdateCheckInterval": "Bakgrundsuppdateringskollfrekvens",
|
||||
"neverManualOnly": "Never - Manual Only",
|
||||
"appearance": "Utseende",
|
||||
"showWebInAppView": "Visa källans hemsida i appvyn",
|
||||
"pinUpdates": "Fäst uppdateringar högst upp i appvyn",
|
||||
"updates": "Uppdateringar",
|
||||
"sourceSpecific": "Källspecifik",
|
||||
"appSource": "Appkälla",
|
||||
"noLogs": "Inga Loggar",
|
||||
"appLogs": "Apploggar",
|
||||
"close": "Stäng",
|
||||
"share": "Dela",
|
||||
"appNotFound": "App ej funnen",
|
||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||
"pickAnAPK": "Välj en APK",
|
||||
"appHasMoreThanOnePackage": "{} har fler än ett paket:",
|
||||
"deviceSupportsXArch": "Din enhet stödjer {} CPU-arkiktektur.",
|
||||
"deviceSupportsFollowingArchs": "YDin enhet stödjer följande CPU-arkitekturer:",
|
||||
"warning": "Varning",
|
||||
"sourceIsXButPackageFromYPrompt": "Appens källa är '{}' men releasepaketet kommer från '{}'. Vill du fortsätta?",
|
||||
"updatesAvailable": "Uppdateringar Tillgängliga",
|
||||
"updatesAvailableNotifDescription": "Aviserar användaren att det finns uppdateringar tillgängaliga för en eller fler Appar som följs av Obtainium",
|
||||
"noNewUpdates": "Inga nya uppdateringar.",
|
||||
"xHasAnUpdate": "{} har en uppdatering.",
|
||||
"appsUpdated": "Appar Uppdaterade",
|
||||
"appsUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were applied in the background",
|
||||
"xWasUpdatedToY": "{} uppdaterades till {}.",
|
||||
"errorCheckingUpdates": "Fel vid uppdateringskoll",
|
||||
"errorCheckingUpdatesNotifDescription": "En aviserings som visar när bakgrundsuppdateringarkollar misslyckas",
|
||||
"appsRemoved": "Appar borttagna",
|
||||
"appsRemovedNotifDescription": "Aviserar användaren när en eller fler Appar togs bort på grund av fel när de laddades",
|
||||
"xWasRemovedDueToErrorY": "{} togs bort på grund av detta felet: {}",
|
||||
"completeAppInstallation": "Gör klar appinstallation",
|
||||
"obtainiumMustBeOpenToInstallApps": "Obtainium måste vara öppet för att installera Appar",
|
||||
"completeAppInstallationNotifDescription": "Frågar användaren att återvända till Obtaiunium när appinstallation är klar",
|
||||
"checkingForUpdates": "Kollar efter Uppdateringar",
|
||||
"checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates",
|
||||
"pleaseAllowInstallPerm": "Tillåt Obtanium att installera Appar",
|
||||
"trackOnly": "Följ-Endast",
|
||||
"errorWithHttpStatusCode": "Fel {}",
|
||||
"versionCorrectionDisabled": "Versionskorrigering inaktiverat (plugin verkar inte fungera)",
|
||||
"unknown": "Okänd",
|
||||
"none": "None",
|
||||
"never": "Aldrig",
|
||||
"latestVersionX": "Senaste Version: {}",
|
||||
"installedVersionX": "Installerad Version: {}",
|
||||
"lastUpdateCheckX": "Senaste uppdateringskoll: {}",
|
||||
"remove": "Ta bort",
|
||||
"yesMarkUpdated": "Ja, Märk som Uppdaterad",
|
||||
"fdroid": "F-Droid Officiell",
|
||||
"appIdOrName": "App-ID eller Namn",
|
||||
"appId": "App-ID",
|
||||
"appWithIdOrNameNotFound": "Ingen App funnen med det namnet eller ID",
|
||||
"reposHaveMultipleApps": "Förråd kan innehålla flera ApparR",
|
||||
"fdroidThirdPartyRepo": "F-Droid Tredjeparts Förråd",
|
||||
"steam": "Steam",
|
||||
"steamMobile": "Steam Mobile",
|
||||
"steamChat": "Steam Chat",
|
||||
"install": "Installera",
|
||||
"markInstalled": "Märk Installerad",
|
||||
"update": "Uppdatera",
|
||||
"markUpdated": "Märk Uppdaterad",
|
||||
"additionalOptions": "Ytterligare Alternativ",
|
||||
"disableVersionDetection": "Inaktivera versionsdetektering",
|
||||
"noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.",
|
||||
"downloadingX": "Laddar ner {}",
|
||||
"downloadNotifDescription": "Notifies the user of the progress in downloading an App",
|
||||
"noAPKFound": "Ingen APK funnen",
|
||||
"noVersionDetection": "Ingen versiondetektering",
|
||||
"categorize": "Kategorisera",
|
||||
"categories": "Kategorier",
|
||||
"category": "Kategori",
|
||||
"noCategory": "Ingen Kategori",
|
||||
"noCategories": "Inga Kategorier",
|
||||
"deleteCategoriesQuestion": "Ta Bort Kategorier?",
|
||||
"categoryDeleteWarning": "Alla Appar i de borttagna kategorierna kommer att märkas som okategoriserade.",
|
||||
"addCategory": "Lägg till Kategori",
|
||||
"label": "Label",
|
||||
"language": "Språk",
|
||||
"copiedToClipboard": "Kopierat till Urklipp",
|
||||
"storagePermissionDenied": "Lagringsbehörighet nekad",
|
||||
"selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.",
|
||||
"filterAPKsByRegEx": "Filter APKs by Regular Expression",
|
||||
"removeFromObtainium": "Ta bort från Obtainium",
|
||||
"uninstallFromDevice": "Avinstallera från Enheten",
|
||||
"onlyWorksWithNonVersionDetectApps": "Fungerar bara för Appar med versionsdetektering inaktiverat..",
|
||||
"releaseDateAsVersion": "Använd releasedatum som version",
|
||||
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
||||
"changes": "Ändringar",
|
||||
"releaseDate": "Releasedatum",
|
||||
"importFromURLsInFile": "Importera från URL:er i fil (som OPML)",
|
||||
"versionDetection": "Versionsdetektering",
|
||||
"standardVersionDetection": "Standardversionsdetektering",
|
||||
"groupByCategory": "Gruppera via Kategori",
|
||||
"autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible",
|
||||
"overrideSource": "Överskrid Källa",
|
||||
"dontShowAgain": "Visa inte detta igen",
|
||||
"dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar",
|
||||
"dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar",
|
||||
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)",
|
||||
"about": "Om",
|
||||
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Kolla efter uppdateringar vid start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
||||
"pickHighestVersionCode": "Auto-select highest version code APK",
|
||||
"checkUpdateOnDetailPage": "Check for updates on opening an App detail page",
|
||||
"disablePageTransitions": "Disable page transition animations",
|
||||
"reversePageTransitions": "Reverse page transition animations",
|
||||
"minStarCount": "Minsta antal stjärnmarkeringar",
|
||||
"addInfoBelow": "Lägg till denna information nedanför.",
|
||||
"addInfoInSettings": "Lägg till denna information i Inställningar.",
|
||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
||||
"appsPossiblyUpdated": "App Updates Attempted",
|
||||
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
|
||||
"xWasPossiblyUpdatedToY": "{} may have been updated to {}.",
|
||||
"enableBackgroundUpdates": "Aktivera Bakgrundsuppdateringar",
|
||||
"backgroundUpdateReqsExplanation": "Bakgrundsuppdateringar är inte möjligt för alla appar.",
|
||||
"backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.",
|
||||
"verifyLatestTag": "Verifiera 'senaste'-taggen",
|
||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First",
|
||||
"intermediateLinkNotFound": "Intermediate link not found",
|
||||
"exemptFromBackgroundUpdates": "Undta från bakgrundsuppdateringar (om aktiverad)",
|
||||
"bgUpdatesOnWiFiOnly": "Inaktivera Bakgrundsuppdateringar utan WiFi",
|
||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
||||
"matchGroupToUse": "Match Group to Use",
|
||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||
"pickExportDir": "Välj Exportsökväg",
|
||||
"autoExportOnChanges": "Automatisk export vid ändringar",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
||||
"dontSortReleasesList": "Retain release order from API",
|
||||
"reverseSort": "Omvänd sortering",
|
||||
"debugMenu": "Felsökningsmeny",
|
||||
"bgTaskStarted": "Background task started - check logs.",
|
||||
"runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu",
|
||||
"removeAppQuestion": {
|
||||
"one": "Ta Bort App?",
|
||||
"other": "Ta Bort Appar?"
|
||||
},
|
||||
"tooManyRequestsTryAgainInMinutes": {
|
||||
"one": "Too many requests (rate limited) - try again in {} minute",
|
||||
"other": "Too many requests (rate limited) - try again in {} minutes"
|
||||
},
|
||||
"bgUpdateGotErrorRetryInMinutes": {
|
||||
"one": "BG update checking encountered a {}, will schedule a retry check in {} minute",
|
||||
"other": "BG update checking encountered a {}, will schedule a retry check in {} minutes"
|
||||
},
|
||||
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||
"one": "BG update checking found {} update - will notify user if needed",
|
||||
"other": "BG update checking found {} updates - will notify user if needed"
|
||||
},
|
||||
"apps": {
|
||||
"one": "{} App",
|
||||
"other": "{} Appar"
|
||||
},
|
||||
"url": {
|
||||
"one": "{} URL",
|
||||
"other": "{} URL:er"
|
||||
},
|
||||
"minute": {
|
||||
"one": "{} Minut",
|
||||
"other": "{} Minuter"
|
||||
},
|
||||
"hour": {
|
||||
"one": "{} Timme",
|
||||
"other": "{} Timmar"
|
||||
},
|
||||
"day": {
|
||||
"one": "{} Dag",
|
||||
"other": "{} Dagar"
|
||||
},
|
||||
"clearedNLogsBeforeXAfterY": {
|
||||
"one": "Rensade {n} logg (före = {before}, efter = {after})",
|
||||
"other": "Rensade {n} loggar (före = {before}, efter = {after})"
|
||||
},
|
||||
"xAndNMoreUpdatesAvailable": {
|
||||
"one": "{} och 1 app till har tillgängliga uppdateringar.",
|
||||
"other": "{} och {} appar till har tillgängliga uppdateringar."
|
||||
},
|
||||
"xAndNMoreUpdatesInstalled": {
|
||||
"one": "{} och 1 till app uppdaterades.",
|
||||
"other": "{} och {} appar till uppdaterades."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} och 1 till app kan ha uppdaterats.",
|
||||
"other": "{} och {} appar till kan ha uppdaterats."
|
||||
}
|
||||
}
|
333
assets/translations/tr.json
Normal file
333
assets/translations/tr.json
Normal file
@ -0,0 +1,333 @@
|
||||
{
|
||||
"invalidURLForSource": "Geçerli bir {} Uygulama URL'si değil",
|
||||
"noReleaseFound": "Uygun bir sürüm bulunamadı",
|
||||
"noVersionFound": "Sürüm bulunamadı",
|
||||
"urlMatchesNoSource": "URL, bilinen bir kaynağa uymuyor",
|
||||
"cantInstallOlderVersion": "Eski bir sürümü yükleyemem",
|
||||
"appIdMismatch": "İndirilen paket kimliği mevcut Uygulama kimliği ile eşleşmiyor",
|
||||
"functionNotImplemented": "Bu sınıf bu işlevi uygulamamıştır",
|
||||
"placeholder": "Yer Tutucu",
|
||||
"someErrors": "Bazı Hatalar Oluştu",
|
||||
"unexpectedError": "Beklenmeyen Hata",
|
||||
"ok": "Tamam",
|
||||
"and": "ve",
|
||||
"githubPATLabel": "GitHub Kişisel Erişim Anahtarı (Sınırlamayı Artırır)",
|
||||
"includePrereleases": "Ön sürümleri dahil et",
|
||||
"fallbackToOlderReleases": "Daha eski sürümlere geri dön",
|
||||
"filterReleaseTitlesByRegEx": "Düzenli İfadelerle Sürüm Başlıklarını Filtrele",
|
||||
"invalidRegEx": "Geçersiz düzenli ifade",
|
||||
"noDescription": "Açıklama yok",
|
||||
"cancel": "İptal",
|
||||
"continue": "Devam Et",
|
||||
"requiredInBrackets": "(Gerekli)",
|
||||
"dropdownNoOptsError": "HATA: DİPLOMADA EN AZ BİR SEÇENEK OLMALI",
|
||||
"colour": "Renk",
|
||||
"githubStarredRepos": "GitHub'a Yıldızlı Depolar",
|
||||
"uname": "Kullanıcı Adı",
|
||||
"wrongArgNum": "Hatalı argüman sayısı sağlandı",
|
||||
"xIsTrackOnly": "{} yalnızca Takip Edilen",
|
||||
"source": "Kaynak",
|
||||
"app": "Uygulama",
|
||||
"appsFromSourceAreTrackOnly": "Bu kaynaktan gelen uygulamalar 'Yalnızca Takip Edilen'dir.",
|
||||
"youPickedTrackOnly": "'Yalnızca Takip Edilen' seçeneğini seçtiniz.",
|
||||
"trackOnlyAppDescription": "Uygulama güncellemeleri için takip edilecek, ancak Obtainium onu indiremeyecek veya kuramayacaktır.",
|
||||
"cancelled": "İptal Edildi",
|
||||
"appAlreadyAdded": "Uygulama zaten eklenmiş",
|
||||
"alreadyUpToDateQuestion": "Uygulama Zaten Güncel mi?",
|
||||
"addApp": "Uygulama Ekle",
|
||||
"appSourceURL": "Uygulama Kaynak URL'si",
|
||||
"error": "Hata",
|
||||
"add": "Ekle",
|
||||
"searchSomeSourcesLabel": "Ara (Bazı Kaynaklar Yalnızca)",
|
||||
"search": "Ara",
|
||||
"additionalOptsFor": "{} İçin Ek Seçenekler",
|
||||
"supportedSources": "Desteklenen Kaynaklar",
|
||||
"trackOnlyInBrackets": "(Yalnızca Takip)",
|
||||
"searchableInBrackets": "(Aranabilir)",
|
||||
"appsString": "Uygulamalar",
|
||||
"noApps": "Uygulama Yok",
|
||||
"noAppsForFilter": "Filtre İçin Uygulama Yok",
|
||||
"byX": "{} Tarafından",
|
||||
"percentProgress": "İlerleme: {}%",
|
||||
"pleaseWait": "Lütfen Bekleyin",
|
||||
"updateAvailable": "Güncelleme Var",
|
||||
"estimateInBracketsShort": "(Est.)",
|
||||
"notInstalled": "Yüklenmedi",
|
||||
"estimateInBrackets": "(Tahmini)",
|
||||
"selectAll": "Hepsini Seç",
|
||||
"deselectX": "{}'yi Seçimden Kaldır",
|
||||
"xWillBeRemovedButRemainInstalled": "{} Obtainium'dan kaldırılacak ancak cihazınızda yüklü kalacaktır.",
|
||||
"removeSelectedAppsQuestion": "Seçilen Uygulamaları Kaldırmak İstiyor musunuz?",
|
||||
"removeSelectedApps": "Seçilen Uygulamaları Kaldır",
|
||||
"updateX": "{}'yi Güncelle",
|
||||
"installX": "{}'yi Yükle",
|
||||
"markXTrackOnlyAsUpdated": "{}(Takip Edilen) olarak Güncellendi olarak İşaretle",
|
||||
"changeX": "{}'yi Değiştir",
|
||||
"installUpdateApps": "Uygulamaları Yükle/Güncelle",
|
||||
"installUpdateSelectedApps": "Seçilen Uygulamaları Yükle/Güncelle",
|
||||
"markXSelectedAppsAsUpdated": "Seçilen Uygulamaları {} olarak Güncellendi olarak İşaretle?",
|
||||
"no": "Hayır",
|
||||
"yes": "Evet",
|
||||
"markSelectedAppsUpdated": "Seçilen Uygulamaları Güncellendi olarak İşaretle",
|
||||
"pinToTop": "Üstte Tut",
|
||||
"unpinFromTop": "Üstten Kaldır",
|
||||
"resetInstallStatusForSelectedAppsQuestion": "Seçilen Uygulamaların Yükleme Durumunu Sıfırlamak İstiyor musunuz?",
|
||||
"installStatusOfXWillBeResetExplanation": "Seçilen Uygulamaların yükleme durumu sıfırlanacak.\n\nBu, Obtainium'da gösterilen uygulama sürümünün başarısız güncellemeler veya diğer sorunlar nedeniyle yanlış olması durumunda yardımcı olabilir.",
|
||||
"shareSelectedAppURLs": "Seçilen Uygulama URL'larını Paylaş",
|
||||
"resetInstallStatus": "Yükleme Durumunu Sıfırla",
|
||||
"more": "Daha Fazla",
|
||||
"removeOutdatedFilter": "Güncel Olmayan Uygulama Filtresini Kaldır",
|
||||
"showOutdatedOnly": "Yalnızca Güncel Olmayan Uygulamaları Göster",
|
||||
"filter": "Filtre",
|
||||
"filterActive": "Filtre *",
|
||||
"filterApps": "Uygulamaları Filtrele",
|
||||
"appName": "Uygulama Adı",
|
||||
"author": "Yazar",
|
||||
"upToDateApps": "Güncel Uygulamalar",
|
||||
"nonInstalledApps": "Yüklenmemiş Uygulamalar",
|
||||
"importExport": "İçe/Dışa Aktar",
|
||||
"settings": "Ayarlar",
|
||||
"exportedTo": "{}'e Dışa Aktarıldı",
|
||||
"obtainiumExport": "Obtainium Dışa Aktar",
|
||||
"invalidInput": "Geçersiz Giriş",
|
||||
"importedX": "{} İçe Aktarıldı",
|
||||
"obtainiumImport": "Obtainium İçe Aktar",
|
||||
"importFromURLList": "URL Listesinden İçe Aktar (Örneğin OPML)",
|
||||
"searchQuery": "Arama Sorgusu",
|
||||
"appURLList": "Uygulama URL Listesi",
|
||||
"line": "Satır",
|
||||
"searchX": "{}'yi Ara",
|
||||
"noResults": "Sonuç Bulunamadı",
|
||||
"importX": "{} İçe Aktar",
|
||||
"importedAppsIdDisclaimer": "İçe Aktarılan Uygulamalar yanlışlıkla \"Yüklenmedi\" olarak gösterilebilir.\nBunu düzeltmek için bunları Obtainium üzerinden yeniden yükleyin.\nBu, yalnızca URL ve üçüncü taraf içe aktarma yöntemlerini etkiler.\n\nYalnızca URL ve üçüncü taraf içe aktarma yöntemlerini etkiler.",
|
||||
"importErrors": "İçe Aktarma Hataları",
|
||||
"importedXOfYApps": "{}'den {} Uygulama İçe Aktarıldı.",
|
||||
"followingURLsHadErrors": "Aşağıdaki URL'lerde hatalar oluştu:",
|
||||
"okay": "Tamam",
|
||||
"selectURL": "URL Seç",
|
||||
"selectURLs": "URL'leri Seç",
|
||||
"pick": "Seç",
|
||||
"theme": "Tema",
|
||||
"dark": "Koyu",
|
||||
"light": "Aydınlık",
|
||||
"followSystem": "Sistemi Takip Et",
|
||||
"obtainium": "Obtainium",
|
||||
"materialYou": "Material You",
|
||||
"useBlackTheme": "Saf siyah koyu temasını kullan",
|
||||
"appSortBy": "Uygulama Sıralama Ölçütü",
|
||||
"authorName": "Yazar/Ad",
|
||||
"nameAuthor": "Ad/Yazar",
|
||||
"asAdded": "Eklendiği Gibi",
|
||||
"appSortOrder": "Uygulama Sıralama Sırası",
|
||||
"ascending": "Artan",
|
||||
"descending": "Azalan",
|
||||
"bgUpdateCheckInterval": "Arka Planda Güncelleme Kontrol Aralığı",
|
||||
"neverManualOnly": "Asla - Yalnızca El ile",
|
||||
"appearance": "Görünüm",
|
||||
"showWebInAppView": "Kaynağı Uygulama Görünümünde Göster",
|
||||
"pinUpdates": "Güncellemeleri Uygulamalar Görünümünün Üstüne Sabitle",
|
||||
"updates": "Güncellemeler",
|
||||
"sourceSpecific": "Kaynak Özel",
|
||||
"appSource": "Uygulama Kaynağı",
|
||||
"noLogs": "Günlük Yok",
|
||||
"appLogs": "Uygulama Günlükleri",
|
||||
"close": "Kapat",
|
||||
"share": "Paylaş",
|
||||
"appNotFound": "Uygulama Bulunamadı",
|
||||
"obtainiumExportHyphenatedLowercase": "obtainium-ihracat",
|
||||
"pickAnAPK": "APK Seç",
|
||||
"appHasMoreThanOnePackage": "{}'nin birden fazla paketi var:",
|
||||
"deviceSupportsXArch": "Cihazınız {} CPU mimarisini destekliyor.",
|
||||
"deviceSupportsFollowingArchs": "Cihazınız aşağıdaki CPU mimarilerini destekliyor:",
|
||||
"warning": "Uyarı",
|
||||
"sourceIsXButPackageFromYPrompt": "Uygulama kaynağı '{}', ancak dağıtım paketi '{}'. Devam etmek istiyor musunuz?",
|
||||
"updatesAvailable": "Güncellemeler Var",
|
||||
"updatesAvailableNotifDescription": "Kullanıcıya Obtainium tarafından takip edilen bir veya daha fazla uygulama için güncelleme bulunduğuna dair bilgi verir",
|
||||
"noNewUpdates": "Yeni güncelleme yok.",
|
||||
"xHasAnUpdate": "{} güncelleme alıyor.",
|
||||
"appsUpdated": "Uygulamalar Güncellendi",
|
||||
"appsUpdatedNotifDescription": "Kullanıcıya bir veya daha fazla uygulamanın arka planda güncellendiğine dair bilgi verir",
|
||||
"xWasUpdatedToY": "{} şu sürüme güncellendi: {}.",
|
||||
"errorCheckingUpdates": "Güncellemeler Kontrol Edilirken Hata Oluştu",
|
||||
"errorCheckingUpdatesNotifDescription": "Arka planda güncelleme kontrolü sırasında hata oluştuğunda görünen bir bildirim",
|
||||
"appsRemoved": "Uygulamalar Kaldırıldı",
|
||||
"appsRemovedNotifDescription": "Bir veya daha fazla uygulamanın yüklenirken hata nedeniyle kaldırıldığını bildiren bir bildirim",
|
||||
"xWasRemovedDueToErrorY": "{} şu hatadan dolayı kaldırıldı: {}",
|
||||
"completeAppInstallation": "Uygulama Yüklemeyi Tamamla",
|
||||
"obtainiumMustBeOpenToInstallApps": "Uygulamaları yüklemek için Obtainium'un açık olması gerekiyor",
|
||||
"completeAppInstallationNotifDescription": "Kullanıcıdan Obtainium'a geri dönüp bir uygulama yüklemeyi tamamlamasını isteyen bir bildirim",
|
||||
"checkingForUpdates": "Güncellemeler Kontrol Ediliyor",
|
||||
"checkingForUpdatesNotifDescription": "Güncellemeler kontrol edildiğinde görünen geçici bir bildirim",
|
||||
"pleaseAllowInstallPerm": "Lütfen Obtainium'un uygulama yüklemesine izin verin",
|
||||
"trackOnly": "Sadece Takip Et",
|
||||
"errorWithHttpStatusCode": "Hata {}",
|
||||
"versionCorrectionDisabled": "Sürüm düzeltme devre dışı bırakıldı (eklenti çalışmıyor gibi görünüyor)",
|
||||
"unknown": "Bilinmiyor",
|
||||
"none": "Hiçbiri",
|
||||
"never": "Asla",
|
||||
"latestVersionX": "En Son Sürüm: {}",
|
||||
"installedVersionX": "Yüklenen Sürüm: {}",
|
||||
"lastUpdateCheckX": "Son Güncelleme Kontrolü: {}",
|
||||
"remove": "Kaldır",
|
||||
"yesMarkUpdated": "Evet, Güncellendi olarak İşaretle",
|
||||
"fdroid": "F-Droid Resmi",
|
||||
"appIdOrName": "Uygulama Kimliği veya Adı",
|
||||
"appId": "Uygulama Kimliği",
|
||||
"appWithIdOrNameNotFound": "Bu kimlik veya ada sahip bir uygulama bulunamadı",
|
||||
"reposHaveMultipleApps": "Depolar birden fazla uygulama içerebilir",
|
||||
"fdroidThirdPartyRepo": "F-Droid Üçüncü Taraf Depo",
|
||||
"steam": "Steam",
|
||||
"steamMobile": "Steam Mobile",
|
||||
"steamChat": "Steam Sohbet",
|
||||
"install": "Yükle",
|
||||
"markInstalled": "Yüklendi olarak İşaretle",
|
||||
"update": "Güncelle",
|
||||
"markUpdated": "Güncellendi olarak İşaretle",
|
||||
"additionalOptions": "Ek Seçenekler",
|
||||
"disableVersionDetection": "Sürüm Algılama Devre Dışı",
|
||||
"noVersionDetectionExplanation": "Bu seçenek, sürüm algılamanın doğru çalışmadığı uygulamalar için kullanılmalıdır.",
|
||||
"downloadingX": "{} İndiriliyor",
|
||||
"downloadNotifDescription": "Bir uygulamanın indirme sürecinde ilerlemeyi bildiren bir bildirim",
|
||||
"noAPKFound": "APK bulunamadı",
|
||||
"noVersionDetection": "Sürüm Algılanamıyor",
|
||||
"categorize": "Kategorize Et",
|
||||
"categories": "Kategoriler",
|
||||
"category": "Kategori",
|
||||
"noCategory": "Kategori Yok",
|
||||
"noCategories": "Kategoriler Yok",
|
||||
"deleteCategoriesQuestion": "Kategorileri Silmek İstiyor musunuz?",
|
||||
"categoryDeleteWarning": "Silinen kategorilerdeki tüm uygulamalar kategorisiz olarak ayarlanacaktır.",
|
||||
"addCategory": "Kategori Ekle",
|
||||
"label": "Etiket",
|
||||
"language": "Dil",
|
||||
"copiedToClipboard": "Panoya Kopyalandı",
|
||||
"storagePermissionDenied": "Depolama izni reddedildi",
|
||||
"selectedCategorizeWarning": "Bu, seçilen uygulamalar için mevcut kategori ayarlarını değiştirecektir.",
|
||||
"filterAPKsByRegEx": "APK'leri Düzenli İfade ile Filtrele",
|
||||
"removeFromObtainium": "Obtainium'dan Kaldır",
|
||||
"uninstallFromDevice": "Cihazdan Kaldır",
|
||||
"onlyWorksWithNonVersionDetectApps": "Yalnızca Sürüm Algılaması Devre Dışı Uygulamalar İçin Çalışır.",
|
||||
"releaseDateAsVersion": "Sürüm Olarak Yayın Tarihi Kullan",
|
||||
"releaseDateAsVersionExplanation": "Bu seçenek, sürüm algılamanın doğru çalışmadığı ancak bir sürüm tarihinin mevcut olduğu uygulamalar için kullanılmalıdır.",
|
||||
"changes": "Değişiklikler",
|
||||
"releaseDate": "Yayın Tarihi",
|
||||
"importFromURLsInFile": "Dosyadaki URL'lerden İçe Aktar",
|
||||
"versionDetection": "Sürüm Tespiti",
|
||||
"standardVersionDetection": "Standart sürüm tespiti",
|
||||
"groupByCategory": "Kategoriye Göre Grupla",
|
||||
"autoApkFilterByArch": "Mümkünse APK'leri CPU mimarisi ile filtreleme girişimi",
|
||||
"overrideSource": "Kaynağı Geçersiz Kıl",
|
||||
"dontShowAgain": "Bunu tekrar gösterme",
|
||||
"dontShowTrackOnlyWarnings": "'Yalnızca Takip Edilen' uyarılarını gösterme",
|
||||
"dontShowAPKOriginWarnings": "APK kaynağı uyarılarını gösterme",
|
||||
"moveNonInstalledAppsToBottom": "Yüklenmemiş Uygulamaları Uygulamalar Görünümünün Altına Taşı",
|
||||
"gitlabPATLabel": "GitLab Kişisel Erişim Belirteci\n(Arama ve Daha İyi APK Keşfi İçin)",
|
||||
"about": "Hakkında",
|
||||
"requiresCredentialsInSettings": "{}: Bu, ek kimlik bilgilerine ihtiyaç duyar (Ayarlar'da)",
|
||||
"checkOnStart": "Başlangıçta güncellemeleri kontrol et",
|
||||
"tryInferAppIdFromCode": "Uygulama kimliğini kaynak kodundan çıkarma girişimi",
|
||||
"removeOnExternalUninstall": "Harici kaldırmada otomatik olarak kaldırılan uygulamalar",
|
||||
"pickHighestVersionCode": "Otomatik olarak en yüksek sürüm kodlu APK'yi seç",
|
||||
"checkUpdateOnDetailPage": "Uygulama detay sayfasını açarken güncellemeleri kontrol et",
|
||||
"disablePageTransitions": "Sayfa geçiş animasyonlarını devre dışı bırak",
|
||||
"reversePageTransitions": "Sayfa geçiş animasyonlarını tersine çevir",
|
||||
"minStarCount": "Minimum Yıldız Sayısı",
|
||||
"addInfoBelow": "Bu bilgiyi aşağıya ekle.",
|
||||
"addInfoInSettings": "Bu bilgiyi Ayarlar'da ekleyin.",
|
||||
"githubSourceNote": "GitHub hız sınırlaması bir API anahtarı kullanılarak atlanabilir.",
|
||||
"gitlabSourceNote": "GitLab APK çıkarma işlemi bir API anahtarı olmadan çalışmayabilir.",
|
||||
"sortByFileNamesNotLinks": "Bağlantılar yerine dosya adlarına göre sırala",
|
||||
"filterReleaseNotesByRegEx": "Sürüm Notlarını Düzenli İfade ile Filtrele",
|
||||
"customLinkFilterRegex": "Özel APK Bağlantı Filtresi Düzenli İfade ile (Varsayılan '.apk$')",
|
||||
"appsPossiblyUpdated": "Uygulama Güncellemeleri Denendi",
|
||||
"appsPossiblyUpdatedNotifDescription": "Kullanıcıya bir veya daha fazla uygulamanın arka planda potansiyel olarak güncellendiğini bildiren bildirim",
|
||||
"xWasPossiblyUpdatedToY": "{} muhtemelen {} sürümüne güncellendi.",
|
||||
"enableBackgroundUpdates": "Arka plan güncellemelerini etkinleştir",
|
||||
"backgroundUpdateReqsExplanation": "Arka plan güncellemeleri tüm uygulamalar için mümkün olmayabilir.",
|
||||
"backgroundUpdateLimitsExplanation": "Arka plan kurulumunun başarısı, Obtainium'un açıldığında ancak belirlenebilir.",
|
||||
"verifyLatestTag": "'latest' etiketini doğrula",
|
||||
"intermediateLinkRegex": "İlk Ziyaret Edilecek 'Ara' Bağlantısını Filtrele",
|
||||
"intermediateLinkNotFound": "Ara bağlantı bulunamadı",
|
||||
"exemptFromBackgroundUpdates": "Arka plan güncellemelerinden muaf tut (etkinse)",
|
||||
"bgUpdatesOnWiFiOnly": "WiFi olmadığında arka plan güncellemelerini devre dışı bırak",
|
||||
"autoSelectHighestVersionCode": "Otomatik olarak en yüksek sürüm kodunu seç",
|
||||
"versionExtractionRegEx": "Sürüm Çıkarma Düzenli İfade",
|
||||
"matchGroupToUse": "Sürüm Çıkarma Regex için Kullanılacak Eşleşme Grubu",
|
||||
"highlightTouchTargets": "Daha az belirgin dokunma hedeflerini vurgula",
|
||||
"pickExportDir": "Dışa Aktarılacak Klasörü Seç",
|
||||
"autoExportOnChanges": "Değişikliklerde otomatik olarak dışa aktar",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Sürümleri Düzenli İfade ile Filtrele",
|
||||
"trySelectingSuggestedVersionCode": "Önerilen sürüm kodunu seçmeyi dene",
|
||||
"dontSortReleasesList": "API'den sıralama düzenini koru",
|
||||
"reverseSort": "Ters sıralama",
|
||||
"debugMenu": "Hata Ayıklama Menüsü",
|
||||
"bgTaskStarted": "Arka plan görevi başladı - günlükleri kontrol et.",
|
||||
"runBgCheckNow": "Arka Plan Güncelleme Kontrolünü Şimdi Çalıştır",
|
||||
"versionExtractWholePage": "Tüm Sayfaya Sürüm Çıkarma Regex'i Uygula",
|
||||
"installing": "Yükleniyor",
|
||||
"skipUpdateNotifications": "Güncelleme bildirimlerini atla",
|
||||
"updatesAvailableNotifChannel": "Güncellemeler Mevcut",
|
||||
"appsUpdatedNotifChannel": "Güncellenen Uygulamalar",
|
||||
"appsPossiblyUpdatedNotifChannel": "Uygulama Güncellemeleri Denendi",
|
||||
"errorCheckingUpdatesNotifChannel": "Güncellemeler Kontrol Edilirken Hata",
|
||||
"appsRemovedNotifChannel": "Kaldırılan Uygulamalar",
|
||||
"downloadingXNotifChannel": "{} İndiriliyor",
|
||||
"completeAppInstallationNotifChannel": "Uygulama Kurulumu Tamamlandı",
|
||||
"checkingForUpdatesNotifChannel": "Güncellemeler Kontrol Ediliyor",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Yalnızca yüklü ve Yalnızca İzleme Uygulamalarını güncelleme",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "Uygulamayı Kaldır?",
|
||||
"other": "Uygulamaları Kaldır?"
|
||||
},
|
||||
"tooManyRequestsTryAgainInMinutes": {
|
||||
"one": "Çok fazla istek (hız sınırlı) - {} dakika sonra tekrar deneyin",
|
||||
"other": "Çok fazla istek (hız sınırlı) - {} dakika sonra tekrar deneyin"
|
||||
},
|
||||
"bgUpdateGotErrorRetryInMinutes": {
|
||||
"one": "Arka plan güncelleme kontrolü bir hatayla karşılaştı, {} dakika sonra tekrar kontrol edilecek",
|
||||
"other": "Arka plan güncelleme kontrolü bir hatayla karşılaştı, {} dakika sonra tekrar kontrol edilecek"
|
||||
},
|
||||
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||
"one": "Arka plan güncelleme kontrolü {} güncelleme buldu - gerektiğinde kullanıcıyı bilgilendirecek",
|
||||
"other": "Arka plan güncelleme kontrolü {} güncelleme buldu - gerektiğinde kullanıcıyı bilgilendirecek"
|
||||
},
|
||||
"apps": {
|
||||
"one": "{} Uygulama",
|
||||
"other": "{} Uygulamalar"
|
||||
},
|
||||
"url": {
|
||||
"one": "{} URL",
|
||||
"other": "{} URL'ler"
|
||||
},
|
||||
"minute": {
|
||||
"one": "{} Dakika",
|
||||
"other": "{} Dakika"
|
||||
},
|
||||
"hour": {
|
||||
"one": "{} Saat",
|
||||
"other": "{} Saat"
|
||||
},
|
||||
"day": {
|
||||
"one": "{} Gün",
|
||||
"other": "{} Gün"
|
||||
},
|
||||
"clearedNLogsBeforeXAfterY": {
|
||||
"one": "{n} log temizlendi (önce = {before}, sonra = {after})",
|
||||
"other": "{n} log temizlendi (önce = {before}, sonra = {after})"
|
||||
},
|
||||
"xAndNMoreUpdatesAvailable": {
|
||||
"one": "{} ve 1 diğer uygulama güncellemeye sahip.",
|
||||
"other": "{} ve {} daha fazla uygulama güncellemeye sahip."
|
||||
},
|
||||
"xAndNMoreUpdatesInstalled": {
|
||||
"one": "{} ve 1 diğer uygulama güncellendi.",
|
||||
"other": "{} ve {} daha fazla uygulama güncellendi."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||
"one": "{} ve 1 diğer uygulama muhtemelen güncellendi.",
|
||||
"other": "{} ve {} daha fazla uygulama muhtemelen güncellendi."
|
||||
}
|
||||
}
|
333
assets/translations/vi.json
Normal file
333
assets/translations/vi.json
Normal file
@ -0,0 +1,333 @@
|
||||
{
|
||||
"invalidURLForSource": "URL ứng dụng {} không hợp lệ",
|
||||
"noReleaseFound": "Không thể tìm thấy bản phát hành phù hợp",
|
||||
"noVersionFound": "Không thể xác định phiên bản phát hành",
|
||||
"urlMatchesNoSource": "URL không khớp với nguồn đã biết",
|
||||
"cantInstallOlderVersion": "Không thể cài đặt phiên bản cũ hơn của Ứng dụng",
|
||||
"appIdMismatch": "ID gói đã tải xuống không khớp với ID ứng dụng hiện tại",
|
||||
"functionNotImplemented": "Lớp này chưa triển khai chức năng này",
|
||||
"placeholder": "Giữ chỗ",
|
||||
"someErrors": "Đã xảy ra một số lỗi",
|
||||
"unexpectedError": "Lỗi không mong đợi",
|
||||
"ok": "Ôkê",
|
||||
"and": "và",
|
||||
"githubPATLabel": "Mã thông báo truy cập cá nhân GitHub (Tăng tốc độ giới hạn)",
|
||||
"includePrereleases": "Bao gồm các bản phát hành trước",
|
||||
"fallbackToOlderReleases": "Dự phòng về bản phát hành cũ hơn",
|
||||
"filterReleaseTitlesByRegEx": "Lọc tiêu đề bản phát hành theo biểu thức chính quy",
|
||||
"invalidRegEx": "Biểu thức chính quy không hợp lệ",
|
||||
"noDescription": "Không có mô tả",
|
||||
"cancel": "Hủy bỏ",
|
||||
"continue": "Tiếp tục",
|
||||
"requiredInBrackets": "(Yêu cầu)",
|
||||
"dropdownNoOptsError": "LỖI: TẢI XUỐNG PHẢI CÓ ÍT NHẤT MỘT LỰA CHỌN",
|
||||
"colour": "Màu sắc",
|
||||
"githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub",
|
||||
"uname": "Tên người dùng",
|
||||
"wrongArgNum": "Số lượng đối số được cung cấp sai",
|
||||
"xIsTrackOnly": "{}là Chỉ-Theo dõi",
|
||||
"source": "Nguồn",
|
||||
"app": "Ứng dụng",
|
||||
"appsFromSourceAreTrackOnly": "Các ứng dụng từ nguồn này là 'Chỉ-Theo dõi'.",
|
||||
"youPickedTrackOnly": "Bạn đã chọn tùy chọn 'Chỉ-Theo dõi'.",
|
||||
"trackOnlyAppDescription": "Ứng dụng sẽ được theo dõi để cập nhật, nhưng Obtainium sẽ không thể tải xuống hoặc cài đặt nó.",
|
||||
"cancelled": "Đã hủy",
|
||||
"appAlreadyAdded": "Ứng dụng được thêm rồi",
|
||||
"alreadyUpToDateQuestion": "Ứng dụng đã được cập nhật?",
|
||||
"addApp": "Thêm ứng dụng",
|
||||
"appSourceURL": "URL nguồn ứng dụng",
|
||||
"error": "Lỗi",
|
||||
"add": "Thêm",
|
||||
"searchSomeSourcesLabel": "Tìm kiếm (Chỉ một số nguồn)",
|
||||
"search": "Tìm kiếm",
|
||||
"additionalOptsFor": "Tùy chọn bổ sung cho {}",
|
||||
"supportedSources": "Nguồn được hỗ trợ",
|
||||
"trackOnlyInBrackets": "(Chỉ-Theo dõi)",
|
||||
"searchableInBrackets": "(Có thể tìm kiếm)",
|
||||
"appsString": "Ứng dụng",
|
||||
"noApps": "Không có ứng dụng",
|
||||
"noAppsForFilter": "Không có ứng dụng cho bộ lọc",
|
||||
"byX": "Bởi {}",
|
||||
"percentProgress": "Tiến triển: {}%",
|
||||
"pleaseWait": "Vui lòng chờ",
|
||||
"updateAvailable": "Có sẵn bản cập nhật",
|
||||
"estimateInBracketsShort": "(Ước lượng.)",
|
||||
"notInstalled": "Chưa cài đặt",
|
||||
"estimateInBrackets": "(Ước lượng)",
|
||||
"selectAll": "Chọn tất cả",
|
||||
"deselectX": "Bỏ chọn {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} sẽ bị xóa khỏi Obtainium nhưng vẫn còn cài đặt trên thiết bị.",
|
||||
"removeSelectedAppsQuestion": "Xóa ứng dụng đã chọn?",
|
||||
"removeSelectedApps": "Xóa ứng dụng đã chọn",
|
||||
"updateX": "Cập nhật {}",
|
||||
"installX": "Cài đặt {}",
|
||||
"markXTrackOnlyAsUpdated": "Đánh dấu {}\n(Chỉ-Theo dõi)\nnhư là đã cập nhật",
|
||||
"changeX": "Thay đổi {}",
|
||||
"installUpdateApps": "Cài đặt/Cập nhật ứng dụng",
|
||||
"installUpdateSelectedApps": "Cài đặt/Cập nhật ứng dụng đã chọn",
|
||||
"markXSelectedAppsAsUpdated": "Đánh dấu {} ứng dụng đã chọn là đã cập nhật?",
|
||||
"no": "Không",
|
||||
"yes": "Đúng",
|
||||
"markSelectedAppsUpdated": "Đánh dấu các ứng dụng đã chọn là đã cập nhật",
|
||||
"pinToTop": "Ghim đầu trang",
|
||||
"unpinFromTop": "Bỏ ghim khỏi đầu trang",
|
||||
"resetInstallStatusForSelectedAppsQuestion": "Đặt lại trạng thái cài đặt cho ứng dụng đã chọn?",
|
||||
"installStatusOfXWillBeResetExplanation": "Trạng thái cài đặt của mọi Ứng dụng đã chọn sẽ được đặt lại.\n\nĐiều này có thể hữu ích khi phiên bản Ứng dụng hiển thị trong Obtainium không chính xác do cập nhật không thành công hoặc các sự cố khác.",
|
||||
"shareSelectedAppURLs": "Chia sẻ URL ứng dụng đã chọn",
|
||||
"resetInstallStatus": "Đặt lại trạng thái cài đặt",
|
||||
"more": "Nhiều hơn",
|
||||
"removeOutdatedFilter": "Xóa bộ lọc ứng dụng lỗi thời",
|
||||
"showOutdatedOnly": "Chỉ hiển thị các ứng dụng lỗi thời",
|
||||
"filter": "Lọc",
|
||||
"filterActive": "Lọc *",
|
||||
"filterApps": "Lọc ứng dụng",
|
||||
"appName": "Tên ứng dụng",
|
||||
"author": "Tác giả",
|
||||
"upToDateApps": "Ứng dụng cập nhật",
|
||||
"nonInstalledApps": "Ứng dụng chưa được cài đặt",
|
||||
"importExport": "Nhập/Xuất",
|
||||
"settings": "Cài đặt",
|
||||
"exportedTo": "Đã xuất sang {}",
|
||||
"obtainiumExport": "Xuất Obtainium",
|
||||
"invalidInput": "Đầu vào không hợp lệ",
|
||||
"importedX": "Đã nhập {}",
|
||||
"obtainiumImport": "Nhập Obtainium",
|
||||
"importFromURLList": "Nhập từ danh sách URL",
|
||||
"searchQuery": "Truy vấn tìm kiếm",
|
||||
"appURLList": "Danh sách URL ứng dụng",
|
||||
"line": "Hàng",
|
||||
"searchX": "Tìm kiếm {}",
|
||||
"noResults": "Không có kết quả nào được tìm thấy",
|
||||
"importX": "Nhập {}",
|
||||
"importedAppsIdDisclaimer": "Ứng dụng đã nhập có thể hiển thị không chính xác là \"Chưa được cài đặt\".\nĐể khắc phục sự cố này, hãy cài đặt lại chúng thông qua Obtainium.\nĐiều này sẽ không ảnh hưởng đến dữ liệu Ứng dụng.\n\nChỉ ảnh hưởng đến URL và phương thức nhập của bên thứ ba.",
|
||||
"importErrors": "Lỗi nhập",
|
||||
"importedXOfYApps": "{} trong số {} Ứng dụng đã được nhập.",
|
||||
"followingURLsHadErrors": "Các URL sau có lỗi:",
|
||||
"okay": "Ôkê",
|
||||
"selectURL": "Chọn URL",
|
||||
"selectURLs": "Chọn URL",
|
||||
"pick": "Chọn",
|
||||
"theme": "Chủ đề",
|
||||
"dark": "Tối",
|
||||
"light": "Sáng",
|
||||
"followSystem": "Theo hệ thống",
|
||||
"obtainium": "Obtainium",
|
||||
"materialYou": "Material You",
|
||||
"useBlackTheme": "Sử dụng chủ đề tối màu đen thuần túy",
|
||||
"appSortBy": "Sắp xếp ứng dụng theo",
|
||||
"authorName": "Tác giả/Tên",
|
||||
"nameAuthor": "Tên/Tác giả",
|
||||
"asAdded": "Như đã thêm",
|
||||
"appSortOrder": "Thứ tự sắp xếp ứng dụng",
|
||||
"ascending": "Tăng dần",
|
||||
"descending": "Giảm dần",
|
||||
"bgUpdateCheckInterval": "Khoảng thời gian kiểm tra cập nhật nền",
|
||||
"neverManualOnly": "Không bao giờ - Chỉ thủ công",
|
||||
"appearance": "Vẻ ngoài",
|
||||
"showWebInAppView": "Hiển thị trang web Nguồn trong chế độ xem Ứng dụng",
|
||||
"pinUpdates": "Ghim nội dung cập nhật lên đầu chế độ xem Ứng dụng",
|
||||
"updates": "Cập nhật",
|
||||
"sourceSpecific": "Nguồn cụ thể",
|
||||
"appSource": "Nguồn ứng dụng",
|
||||
"noLogs": "Không có nhật ký",
|
||||
"appLogs": "Nhật ký ứng dụng",
|
||||
"close": "Đóng",
|
||||
"share": "Chia sẻ",
|
||||
"appNotFound": "Không tìm thấy ứng dụng",
|
||||
"obtainiumExportHyphenatedLowercase": "xuất khẩu-obtainium",
|
||||
"pickAnAPK": "Chọn một APK",
|
||||
"appHasMoreThanOnePackage": "{} có nhiều gói:",
|
||||
"deviceSupportsXArch": "Thiết bị của bạn hỗ trợ kiến trúc CPU {}.",
|
||||
"deviceSupportsFollowingArchs": "Thiết bị của bạn hỗ trợ các kiến trúc CPU sau:",
|
||||
"warning": "Cảnh báo",
|
||||
"sourceIsXButPackageFromYPrompt": "Nguồn ứng dụng là '{}' nhưng gói phát hành đến từ '{}'. Tiếp tục?",
|
||||
"updatesAvailable": "Cập nhật có sẵn",
|
||||
"updatesAvailableNotifDescription": "Thông báo cho người dùng rằng có bản cập nhật cho một hoặc nhiều Ứng dụng được theo dõi bởi Obtainium",
|
||||
"noNewUpdates": "Không có bản cập nhật mới.",
|
||||
"xHasAnUpdate": "{} có bản cập nhật.",
|
||||
"appsUpdated": "Ứng dụng đã cập nhật ",
|
||||
"appsUpdatedNotifDescription": "Thông báo cho người dùng rằng các bản cập nhật cho một hoặc nhiều Ứng dụng đã được áp dụng trong nền",
|
||||
"xWasUpdatedToY": "{} đã được cập nhật thành {}.",
|
||||
"errorCheckingUpdates": "Lỗi kiểm tra bản cập nhật",
|
||||
"errorCheckingUpdatesNotifDescription": "Thông báo hiển thị khi kiểm tra cập nhật nền không thành công",
|
||||
"appsRemoved": "Ứng dụng đã loại bỏ",
|
||||
"appsRemovedNotifDescription": "Thông báo cho người dùng rằng một hoặc nhiều Ứng dụng đã bị loại bỏ do lỗi khi tải chúng",
|
||||
"xWasRemovedDueToErrorY": "{} đã bị loại bỏ do lỗi này: {}",
|
||||
"completeAppInstallation": "Hoàn tất cài đặt ứng dụng",
|
||||
"obtainiumMustBeOpenToInstallApps": "Obtainium phải được mở để cài đặt Ứng dụng",
|
||||
"completeAppInstallationNotifDescription": "Yêu cầu người dùng quay lại Obtainium để hoàn tất cài đặt Ứng dụng",
|
||||
"checkingForUpdates": "Đang kiểm tra cập nhật",
|
||||
"checkingForUpdatesNotifDescription": "Thông báo tạm thời xuất hiện khi kiểm tra bản cập nhật",
|
||||
"pleaseAllowInstallPerm": "Vui lòng cho phép Obtainium cài đặt Ứng dụng",
|
||||
"trackOnly": "Chỉ-Theo dõi",
|
||||
"errorWithHttpStatusCode": "Lỗi {}",
|
||||
"versionCorrectionDisabled": "Tính năng sửa phiên bản bị vô hiệu hóa (plugin dường như không hoạt động)",
|
||||
"unknown": "Không xác định",
|
||||
"none": "Không",
|
||||
"never": "Không bao giờ",
|
||||
"latestVersionX": "Phiên bản mới nhất: {}",
|
||||
"installedVersionX": "Phiên bản đã cài đặt: {}",
|
||||
"lastUpdateCheckX": "Kiểm tra cập nhật lần cuối: {}",
|
||||
"remove": "Loại bỏ",
|
||||
"yesMarkUpdated": "Có, Đánh dấu là đã cập nhật",
|
||||
"fdroid": "Chính thức của F-Droid",
|
||||
"appIdOrName": "ID hoặc tên ứng dụng",
|
||||
"appId": "ID ứng dụng",
|
||||
"appWithIdOrNameNotFound": "Không tìm thấy ứng dụng nào có ID hoặc tên đó",
|
||||
"reposHaveMultipleApps": "Kho có thể chứa nhiều Ứng dụng",
|
||||
"fdroidThirdPartyRepo": "Kho lưu trữ bên thứ ba F-Droid",
|
||||
"steam": "Steam",
|
||||
"steamMobile": "Steam Mobile",
|
||||
"steamChat": "Steam Chat",
|
||||
"install": "Cài đặt",
|
||||
"markInstalled": "Đánh dấu là đã cài đặt",
|
||||
"update": "Cập nhật",
|
||||
"markUpdated": "Đánh dấu đã cập nhật",
|
||||
"additionalOptions": "Tùy chọn bổ sung",
|
||||
"disableVersionDetection": "Tắt tính năng phát hiện phiên bản",
|
||||
"noVersionDetectionExplanation": "Chỉ nên sử dụng tùy chọn này cho Ứng dụng mà tính năng phát hiện phiên bản không hoạt động chính xác.",
|
||||
"downloadingX": "Đang tải xuống {}",
|
||||
"downloadNotifDescription": "Thông báo cho người dùng về tiến trình tải xuống Ứng dụng",
|
||||
"noAPKFound": "Không tìm thấy APK",
|
||||
"noVersionDetection": "Không phát hiện phiên bản",
|
||||
"categorize": "Phân loại",
|
||||
"categories": "Thể loại",
|
||||
"category": "Thể loại",
|
||||
"noCategory": "Không thể loại",
|
||||
"noCategories": "Không thể loại",
|
||||
"deleteCategoriesQuestion": "Xóa thể loại?",
|
||||
"categoryDeleteWarning": "Tất cả ứng dụng trong thể loại đã xóa sẽ được đặt thành chưa được phân loại.",
|
||||
"addCategory": "Thêm thể loại",
|
||||
"label": "Nhãn",
|
||||
"language": "Ngôn ngữ",
|
||||
"copiedToClipboard": "Sao chép vào clipboard",
|
||||
"storagePermissionDenied": "Quyền lưu trữ bị từ chối",
|
||||
"selectedCategorizeWarning": "Điều này sẽ thay thế mọi cài đặt thể loại hiện có cho Ứng dụng đã chọn.",
|
||||
"filterAPKsByRegEx": "Lọc APK theo biểu thức chính quy",
|
||||
"removeFromObtainium": "Loại khỏi Obtainium",
|
||||
"uninstallFromDevice": "Gỡ cài đặt khỏi thiết bị",
|
||||
"onlyWorksWithNonVersionDetectApps": "Chỉ hoạt động với Ứng dụng đã tắt tính năng phát hiện phiên bản.",
|
||||
"releaseDateAsVersion": "Sử dụng ngày phát hành làm phiên bản",
|
||||
"releaseDateAsVersionExplanation": "Chỉ nên sử dụng tùy chọn này cho Ứng dụng trong đó tính năng phát hiện phiên bản không hoạt động chính xác nhưng đã có ngày phát hành.",
|
||||
"changes": "Thay đổi",
|
||||
"releaseDate": "Ngày phát hành",
|
||||
"importFromURLsInFile": "Nhập từ URL trong Tệp (như OPML)",
|
||||
"versionDetection": "Phát hiện phiên bản",
|
||||
"standardVersionDetection": "Phát hiện phiên bản tiêu chuẩn",
|
||||
"groupByCategory": "Nhóm theo thể loại",
|
||||
"autoApkFilterByArch": "Cố gắng lọc APK theo kiến trúc CPU nếu có thể",
|
||||
"overrideSource": "Ghi đè nguồn",
|
||||
"dontShowAgain": "Đừng hiển thị thông tin này nữa",
|
||||
"dontShowTrackOnlyWarnings": "Không hiển thị cảnh báo 'Chỉ-Theo dõi'",
|
||||
"dontShowAPKOriginWarnings": "Không hiển thị cảnh báo nguồn gốc APK",
|
||||
"moveNonInstalledAppsToBottom": "Di chuyển Ứng dụng chưa được cài đặt xuống cuối chế độ xem Ứng dụng",
|
||||
"gitlabPATLabel": "Mã thông báo truy cập cá nhân GitLab\n(Cho phép tìm kiếm và khám phá APK tốt hơn)",
|
||||
"about": "Giới thiệu",
|
||||
"requiresCredentialsInSettings": "{}: Điều này cần thông tin xác thực bổ sung (trong Cài đặt)",
|
||||
"checkOnStart": "Kiểm tra các bản cập nhật khi khởi động",
|
||||
"tryInferAppIdFromCode": "Thử suy ra ID ứng dụng từ mã nguồn",
|
||||
"removeOnExternalUninstall": "Tự động xóa ứng dụng đã gỡ cài đặt bên ngoài",
|
||||
"pickHighestVersionCode": "Tự động chọn APK mã phiên bản cao nhất",
|
||||
"checkUpdateOnDetailPage": "Kiểm tra các bản cập nhật khi mở trang chi tiết Ứng dụng",
|
||||
"disablePageTransitions": "Tắt hoạt ảnh chuyển trang",
|
||||
"reversePageTransitions": "Hoạt ảnh chuyển đổi trang đảo ngược",
|
||||
"minStarCount": "Số lượng sao tối thiểu",
|
||||
"addInfoBelow": "Thêm thông tin này vào bên dưới.",
|
||||
"addInfoInSettings": "Thêm thông tin này vào Cài đặt.",
|
||||
"githubSourceNote": "Có thể tránh được việc giới hạn tốc độ GitHub bằng cách sử dụng khóa API.",
|
||||
"gitlabSourceNote": "Trích xuất APK GitLab có thể không hoạt động nếu không có khóa API.",
|
||||
"sortByFileNamesNotLinks": "Sắp xếp theo tên tệp thay vì liên kết đầy đủ",
|
||||
"filterReleaseNotesByRegEx": "Lọc ghi chú phát hành theo biểu thức chính quy",
|
||||
"customLinkFilterRegex": "Bộ lọc liên kết APK tùy chỉnh theo biểu thức chính quy (Mặc định '.apk$')",
|
||||
"appsPossiblyUpdated": "Đã cố gắng cập nhật ứng dụng",
|
||||
"appsPossiblyUpdatedNotifDescription": "Thông báo cho người dùng rằng các bản cập nhật cho một hoặc nhiều Ứng dụng có khả năng được áp dụng trong nền",
|
||||
"xWasPossiblyUpdatedToY": "{} có thể đã được cập nhật thành {}.",
|
||||
"enableBackgroundUpdates": "Bật cập nhật nền",
|
||||
"backgroundUpdateReqsExplanation": "Có thể không thực hiện được cập nhật nền cho tất cả ứng dụng.",
|
||||
"backgroundUpdateLimitsExplanation": "Sự thành công của cài đặt nền chỉ có thể được xác định khi mở Obtainium.",
|
||||
"verifyLatestTag": "Xác minh thẻ 'mới nhất'",
|
||||
"intermediateLinkRegex": "Lọc tìm liên kết 'Trung gian' để truy cập trước",
|
||||
"intermediateLinkNotFound": "Không tìm thấy liên kết trung gian",
|
||||
"exemptFromBackgroundUpdates": "Miễn cập nhật nền (nếu được bật)",
|
||||
"bgUpdatesOnWiFiOnly": "Tắt cập nhật nền khi không có WiFi",
|
||||
"autoSelectHighestVersionCode": "Tự động chọn APK mã phiên bản cao nhất",
|
||||
"versionExtractionRegEx": "Trích xuất phiên bản RegEx",
|
||||
"matchGroupToUse": "Nhóm đối sánh để sử dụng cho Regex trích xuất phiên bản",
|
||||
"highlightTouchTargets": "Đánh dấu các mục tiêu cảm ứng ít rõ ràng hơn",
|
||||
"pickExportDir": "Chọn thư mục xuất",
|
||||
"autoExportOnChanges": "Tự động xuất khi thay đổi",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "Lọc phiên bản theo biểu thức chính quy",
|
||||
"trySelectingSuggestedVersionCode": "Thử chọn APK Mã phiên bản được đề xuất",
|
||||
"dontSortReleasesList": "Giữ lại thứ tự phát hành từ API",
|
||||
"reverseSort": "Sắp xếp ngược",
|
||||
"debugMenu": "Danh sách gỡ lỗi",
|
||||
"bgTaskStarted": "Tác vụ nền đã bắt đầu - kiểm tra nhật ký.",
|
||||
"runBgCheckNow": "Chạy kiểm tra cập nhật nền ngay bây giờ",
|
||||
"versionExtractWholePage": "Áp dụng Regex trích xuất phiên bản cho toàn bộ trang",
|
||||
"installing": "Đang cài đặt",
|
||||
"skipUpdateNotifications": "Bỏ qua thông báo cập nhật",
|
||||
"updatesAvailableNotifChannel": "Cập nhật có sẵn",
|
||||
"appsUpdatedNotifChannel": "Đã cập nhật ứng dụng",
|
||||
"appsPossiblyUpdatedNotifChannel": "Đã cố gắng cập nhật ứng dụng",
|
||||
"errorCheckingUpdatesNotifChannel": "Lỗi kiểm tra bản cập nhật",
|
||||
"appsRemovedNotifChannel": "Ứng dụng đã bị loại bỏ",
|
||||
"downloadingXNotifChannel": "Đang tải xuống {}",
|
||||
"completeAppInstallationNotifChannel": "Hoàn tất cài đặt ứng dụng",
|
||||
"checkingForUpdatesNotifChannel": "Đang kiểm tra cập nhật",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "Chỉ kiểm tra các ứng dụng đã cài đặt và Chỉ-Theo dõi để biết các bản cập nhật",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion":{
|
||||
"one": "Gỡ ứng dụng?",
|
||||
"other": "Gỡ ứng dụng?"
|
||||
},
|
||||
"tooManyRequestsTryAgainInMinutes":{
|
||||
"one": "Quá nhiều yêu cầu (tốc độ giới hạn) - hãy thử lại sau {} phút",
|
||||
"other": "Quá nhiều yêu cầu (tốc độ giới hạn) - hãy thử lại sau {} phút"
|
||||
},
|
||||
"bgUpdateGotErrorRetryInMinutes":{
|
||||
"one": "Việc kiểm tra bản cập nhật BG gặp phải {}, sẽ lên lịch kiểm tra lại sau {} phút",
|
||||
"other": "Việc kiểm tra bản cập nhật BG gặp phải {}, sẽ lên lịch kiểm tra lại sau {} phút"
|
||||
},
|
||||
"bgCheckFoundUpdatesWillNotifyIfNeeded":{
|
||||
"one": "Đang kiểm tra bản cập nhật BG tìm thấy {} bản cập nhật - sẽ thông báo cho người dùng nếu cần",
|
||||
"other": "Đang kiểm tra bản cập nhật BG tìm thấy {} bản cập nhật - sẽ thông báo cho người dùng nếu cần"
|
||||
},
|
||||
"apps":{
|
||||
"one": "{} Ứng dụng",
|
||||
"other": "{} Ứng dụng"
|
||||
},
|
||||
"url":{
|
||||
"one": "{} URL",
|
||||
"other": "{} URL"
|
||||
},
|
||||
"minute":{
|
||||
"one": "{} Phút",
|
||||
"other": "{} Phút"
|
||||
},
|
||||
"hour":{
|
||||
"one": "{} Giờ",
|
||||
"other": "{} Giờ"
|
||||
},
|
||||
"day":{
|
||||
"one": "{} Ngày",
|
||||
"other": "{} ngày"
|
||||
},
|
||||
"clearedNLogsBeforeXAfterY":{
|
||||
"one": "Đã xóa {n} nhật ký (trước = {trước}, sau = {sau})",
|
||||
"other": "Đã xóa {n} nhật ký (trước = {trước}, sau = {sau})"
|
||||
},
|
||||
"xAndNMoreUpdatesAvailable":{
|
||||
"one": "{} và 1 ứng dụng khác có bản cập nhật.",
|
||||
"other": "{} và {} ứng dụng khác có bản cập nhật."
|
||||
},
|
||||
"xAndNMoreUpdatesInstalled":{
|
||||
"one": "{} và 1 ứng dụng khác đã được cập nhật.",
|
||||
"other": "{} và {} ứng dụng khác đã được cập nhật."
|
||||
},
|
||||
"xAndNMoreUpdatesPossiblyInstalled":{
|
||||
"one": "{} và 1 ứng dụng khác có thể đã được cập nhật.",
|
||||
"other": "{} và {} ứng dụng khác có thể đã được cập nhật."
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
"githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)",
|
||||
"includePrereleases": "包含预发行版",
|
||||
"fallbackToOlderReleases": "将旧发行版作为备选",
|
||||
"filterReleaseTitlesByRegEx": "使用正则表达式筛选发行标题",
|
||||
"filterReleaseTitlesByRegEx": "筛选发行标题(正则表达式)",
|
||||
"invalidRegEx": "无效的正则表达式",
|
||||
"noDescription": "无描述",
|
||||
"cancel": "取消",
|
||||
@ -55,7 +55,7 @@
|
||||
"notInstalled": "未安装",
|
||||
"estimateInBrackets": "(推测)",
|
||||
"selectAll": "全选",
|
||||
"deselectN": "取消选择 {}",
|
||||
"deselectX": "取消选择 {}",
|
||||
"xWillBeRemovedButRemainInstalled": "{} 将从 Obtainium 中删除,但仍安装在您的设备中。",
|
||||
"removeSelectedAppsQuestion": "是否删除选中的应用?",
|
||||
"removeSelectedApps": "删除选中的应用",
|
||||
@ -203,7 +203,7 @@
|
||||
"copiedToClipboard": "已复制至剪贴板",
|
||||
"storagePermissionDenied": "已拒绝授予存储权限",
|
||||
"selectedCategorizeWarning": "这将覆盖选中应用当前的类别设置。",
|
||||
"filterAPKsByRegEx": "使用正则表达式筛选 APK 文件",
|
||||
"filterAPKsByRegEx": "筛选 APK 文件(正则表达式)",
|
||||
"removeFromObtainium": "从 Obtainium 中删除",
|
||||
"uninstallFromDevice": "从设备中卸载",
|
||||
"onlyWorksWithNonVersionDetectApps": "仅适用于禁用版本检测的应用。",
|
||||
@ -221,9 +221,9 @@
|
||||
"dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告",
|
||||
"dontShowAPKOriginWarnings": "不显示 APK 文件来源警告",
|
||||
"moveNonInstalledAppsToBottom": "将未安装应用置底",
|
||||
"gitlabPATLabel": "GitLab 个人访问令牌\n(启用搜索功能并增强 APK 发现)",
|
||||
"gitlabPATLabel": "GitLab 个人访问令牌(启用搜索功能并增强 APK 发现)",
|
||||
"about": "相关文档",
|
||||
"requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)",
|
||||
"requiresCredentialsInSettings": "{}: 此功能需要额外的凭据(在“设置”中添加)",
|
||||
"checkOnStart": "启动时进行一次检查",
|
||||
"tryInferAppIdFromCode": "尝试从源代码推断应用 ID",
|
||||
"removeOnExternalUninstall": "自动删除已卸载的外部应用",
|
||||
@ -237,8 +237,8 @@
|
||||
"githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。",
|
||||
"gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。",
|
||||
"sortByFileNamesNotLinks": "使用文件名代替链接进行排序",
|
||||
"filterReleaseNotesByRegEx": "使用正则表达式筛选发行说明",
|
||||
"customLinkFilterRegex": "使用正则表达式筛选自定义来源 APK 文件链接\n(未填写时,默认匹配模式为“.apk$”)",
|
||||
"filterReleaseNotesByRegEx": "筛选发行说明(正则表达式)",
|
||||
"customLinkFilterRegex": "筛选自定义来源 APK 文件链接\n(正则表达式,默认匹配模式为“.apk$”)",
|
||||
"appsPossiblyUpdated": "已尝试更新应用",
|
||||
"appsPossiblyUpdatedNotifDescription": "当应用已尝试在后台更新时发送通知",
|
||||
"xWasPossiblyUpdatedToY": "已尝试将“{}”更新至 {}。",
|
||||
@ -246,26 +246,27 @@
|
||||
"backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。",
|
||||
"backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。",
|
||||
"verifyLatestTag": "验证“Latest”标签",
|
||||
"intermediateLinkRegex": "筛选一个首先访问的“中转”链接(正则表达式)",
|
||||
"intermediateLinkRegex": "筛选首先访问的“中转”链接(正则表达式)",
|
||||
"intermediateLinkNotFound": "未找到“中转”链接",
|
||||
"exemptFromBackgroundUpdates": "单独禁用后台更新(若已经全局启用)",
|
||||
"exemptFromBackgroundUpdates": "禁用后台更新\n(如果已经全局启用)",
|
||||
"bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
|
||||
"autoSelectHighestVersionCode": "自动选择版本号最高的 APK 文件",
|
||||
"versionExtractionRegEx": "获取版本号的正则表达式",
|
||||
"versionExtractionRegEx": "提取版本号(正则表达式)",
|
||||
"matchGroupToUse": "引用的捕获组",
|
||||
"highlightTouchTargets": "突出展示不明显的触摸区域",
|
||||
"pickExportDir": "选择导出文件夹",
|
||||
"autoExportOnChanges": "数据变更时自动导出",
|
||||
"filterVersionsByRegEx": "使用正则表达式筛选版本号",
|
||||
"includeSettings": "Include settings",
|
||||
"filterVersionsByRegEx": "筛选版本号(正则表达式)",
|
||||
"trySelectingSuggestedVersionCode": "尝试选择推荐版本的 APK 文件",
|
||||
"dontSortReleasesList": "保持来自 API 的发行顺序",
|
||||
"reverseSort": "反转排序",
|
||||
"debugMenu": "调试选项",
|
||||
"bgTaskStarted": "后台任务已启动 - 详见日志",
|
||||
"runBgCheckNow": "立即进行后台更新检查",
|
||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||
"installing": "Installing",
|
||||
"skipUpdateNotifications": "Skip update notifications",
|
||||
"versionExtractWholePage": "将提取版本号的正则表达式应用于整个页面",
|
||||
"installing": "正在安装",
|
||||
"skipUpdateNotifications": "忽略更新通知",
|
||||
"updatesAvailableNotifChannel": "更新可用",
|
||||
"appsUpdatedNotifChannel": "应用已更新",
|
||||
"appsPossiblyUpdatedNotifChannel": "已尝试更新应用",
|
||||
@ -274,6 +275,9 @@
|
||||
"downloadingXNotifChannel": "正在下载{}",
|
||||
"completeAppInstallationNotifChannel": "完成应用安装",
|
||||
"checkingForUpdatesNotifChannel": "正在检查更新",
|
||||
"onlyCheckInstalledOrTrackOnlyApps": "只对已安装和“仅追踪”的应用进行更新检查",
|
||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
||||
"selectX": "Select {}",
|
||||
"removeAppQuestion": {
|
||||
"one": "是否删除应用?",
|
||||
"other": "是否删除应用?"
|
||||
|
7
build.sh
7
build.sh
@ -7,8 +7,11 @@ trap "cd "$CURR_DIR"" EXIT
|
||||
if [ -z "$1" ]; then
|
||||
git fetch && git merge origin/main && git push # Typically run after a PR to main, so bring dev up to date
|
||||
fi
|
||||
rm ./build/app/outputs/flutter-apk/* 2>/dev/null # Get rid of older builds if any
|
||||
flutter build apk && flutter build apk --split-per-abi # Build (both split and combined APKs)
|
||||
rm ./build/app/outputs/flutter-apk/* 2>/dev/null # Get rid of older builds if any
|
||||
flutter build apk --flavor normal && flutter build apk --split-per-abi --flavor normal # Build (both split and combined APKs)
|
||||
for file in ./build/app/outputs/flutter-apk/app-*normal*.apk*; do mv "$file" "${file//-normal/}"; done
|
||||
flutter build apk --flavor fdroid -t lib/main_fdroid.dart && # Do the same for the F-Droid flavour
|
||||
flutter build apk --split-per-abi --flavor fdroid -t lib/main_fdroid.dart
|
||||
for file in ./build/app/outputs/flutter-apk/*.sha1; do gpg --sign --detach-sig "$file"; done # Generate PGP signatures
|
||||
rsync -r ./build/app/outputs/flutter-apk/ ~/Downloads/Obtainium-build/ # Dropoff in Downloads to allow for drag-drop into Flatpak Firefox
|
||||
cd ~/Downloads/Obtainium-build/ # Make zips just in case (for in-comment uploads)
|
||||
|
@ -32,7 +32,8 @@ class APKMirror extends AppSource {
|
||||
|
||||
@override
|
||||
String sourceSpecificStandardizeURL(String url) {
|
||||
RegExp standardUrlRegEx = RegExp('^https?://$host/apk/[^/]+/[^/]+');
|
||||
RegExp standardUrlRegEx =
|
||||
RegExp('^https?://(www\\.)?$host/apk/[^/]+/[^/]+');
|
||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
||||
if (match == null) {
|
||||
throw InvalidURLError(name);
|
||||
|
@ -139,11 +139,11 @@ APKDetails getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||
}
|
||||
}
|
||||
// Apply the release filter if any
|
||||
if (filterVersionsByRegEx != null) {
|
||||
if (filterVersionsByRegEx?.isNotEmpty == true) {
|
||||
version = null;
|
||||
releaseChoices = [];
|
||||
for (var i = 0; i < releases.length; i++) {
|
||||
if (RegExp(filterVersionsByRegEx)
|
||||
if (RegExp(filterVersionsByRegEx!)
|
||||
.hasMatch(releases[i]['versionName'])) {
|
||||
version = releases[i]['versionName'];
|
||||
}
|
||||
@ -181,7 +181,7 @@ APKDetails getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||
List<String> apkUrls = releaseChoices
|
||||
.map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk')
|
||||
.toList();
|
||||
return APKDetails(version, getApkUrlsFromUrls(apkUrls),
|
||||
return APKDetails(version, getApkUrlsFromUrls(apkUrls.toSet().toList()),
|
||||
AppNames(sourceName, Uri.parse(standardUrl).pathSegments.last));
|
||||
} else {
|
||||
throw getObtainiumHttpError(res);
|
||||
|
@ -54,17 +54,25 @@ class FDroidRepo extends AppSource {
|
||||
@override
|
||||
Future<Map<String, List<String>>> search(String query,
|
||||
{Map<String, dynamic> querySettings = const {}}) async {
|
||||
query = removeQueryParamsFromUrl(standardizeUrl(query));
|
||||
var res = await sourceRequest('$query/index.xml');
|
||||
String? url = querySettings['url'];
|
||||
if (url == null) {
|
||||
throw NoReleasesError();
|
||||
}
|
||||
url = removeQueryParamsFromUrl(standardizeUrl(url));
|
||||
var res = await sourceRequest('$url/index.xml');
|
||||
if (res.statusCode == 200) {
|
||||
var body = parse(res.body);
|
||||
Map<String, List<String>> results = {};
|
||||
body.querySelectorAll('application').toList().forEach((app) {
|
||||
String appId = app.attributes['id']!;
|
||||
results['$query?appId=$appId'] = [
|
||||
app.querySelector('name')?.innerHtml ?? appId,
|
||||
app.querySelector('desc')?.innerHtml ?? ''
|
||||
];
|
||||
String appName = app.querySelector('name')?.innerHtml ?? appId;
|
||||
String appDesc = app.querySelector('desc')?.innerHtml ?? '';
|
||||
if (query.isEmpty ||
|
||||
appId.contains(query) ||
|
||||
appName.contains(query) ||
|
||||
appDesc.contains(query)) {
|
||||
results['$url?appId=$appId'] = [appName, appDesc];
|
||||
}
|
||||
});
|
||||
return results;
|
||||
} else {
|
||||
@ -108,7 +116,8 @@ class FDroidRepo extends AppSource {
|
||||
if (appIdOrName == null) {
|
||||
throw NoReleasesError();
|
||||
}
|
||||
var res = await sourceRequest('$standardUrl/index.xml');
|
||||
var res = await sourceRequest(
|
||||
'$standardUrl${standardUrl.endsWith('/index.xml') ? '' : '/index.xml'}');
|
||||
if (res.statusCode == 200) {
|
||||
var body = parse(res.body);
|
||||
var foundApps = body.querySelectorAll('application').where((element) {
|
||||
|
@ -117,22 +117,23 @@ class GitHub extends AppSource {
|
||||
.decode(body['content'].toString().split('\n').join('')))
|
||||
.split('\n')
|
||||
.map((e) => e.trim());
|
||||
var appId = trimmedLines
|
||||
.where((l) =>
|
||||
l.startsWith('applicationId "') ||
|
||||
l.startsWith('applicationId \''))
|
||||
.first;
|
||||
appId = appId
|
||||
.split(appId.startsWith('applicationId "') ? '"' : '\'')[1];
|
||||
if (appId.startsWith('\${') && appId.endsWith('}')) {
|
||||
appId = trimmedLines
|
||||
.where((l) => l.startsWith(
|
||||
'def ${appId.substring(2, appId.length - 1)}'))
|
||||
.first;
|
||||
appId = appId.split(appId.contains('"') ? '"' : '\'')[1];
|
||||
}
|
||||
if (appId.isNotEmpty) {
|
||||
var appIds = trimmedLines.where((l) =>
|
||||
l.startsWith('applicationId "') ||
|
||||
l.startsWith('applicationId \''));
|
||||
appIds = appIds.map((appId) => appId
|
||||
.split(appId.startsWith('applicationId "') ? '"' : '\'')[1]);
|
||||
appIds = appIds.map((appId) {
|
||||
if (appId.startsWith('\${') && appId.endsWith('}')) {
|
||||
appId = trimmedLines
|
||||
.where((l) => l.startsWith(
|
||||
'def ${appId.substring(2, appId.length - 1)}'))
|
||||
.first;
|
||||
appId = appId.split(appId.contains('"') ? '"' : '\'')[1];
|
||||
}
|
||||
return appId;
|
||||
}).where((appId) => appId.isNotEmpty);
|
||||
if (appIds.length == 1) {
|
||||
return appIds.first;
|
||||
}
|
||||
} catch (err) {
|
||||
LogsProvider().add(
|
||||
|
@ -80,12 +80,8 @@ class GitLab extends AppSource {
|
||||
@override
|
||||
Future<Map<String, List<String>>> search(String query,
|
||||
{Map<String, dynamic> querySettings = const {}}) async {
|
||||
String? PAT = await getPATIfAny({});
|
||||
if (PAT == null) {
|
||||
throw CredsNeededError(name);
|
||||
}
|
||||
var url =
|
||||
'https://$host/api/v4/search?private_token=$PAT&scope=projects&search=${Uri.encodeQueryComponent(query)}';
|
||||
'https://$host/api/v4/projects?search=${Uri.encodeQueryComponent(query)}';
|
||||
var res = await sourceRequest(url);
|
||||
if (res.statusCode != 200) {
|
||||
throw getObtainiumHttpError(res);
|
||||
@ -174,7 +170,6 @@ class GitLab extends AppSource {
|
||||
...getLinksFromParsedHTML(entryContent,
|
||||
RegExp('/[^/]+\\.apk\$', caseSensitive: false), '')
|
||||
.where((element) => Uri.parse(element).host != '')
|
||||
.toList()
|
||||
];
|
||||
var entryId = entry.querySelector('id')?.innerHtml;
|
||||
var version =
|
||||
@ -192,7 +187,7 @@ class GitLab extends AppSource {
|
||||
});
|
||||
}
|
||||
if (apkDetailsList.isEmpty) {
|
||||
throw NoReleasesError();
|
||||
throw NoReleasesError(note: tr('gitlabSourceNote'));
|
||||
}
|
||||
if (fallbackToOlderReleases) {
|
||||
if (additionalSettings['trackOnly'] != true) {
|
||||
@ -200,7 +195,7 @@ class GitLab extends AppSource {
|
||||
apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList();
|
||||
}
|
||||
if (apkDetailsList.isEmpty) {
|
||||
throw NoReleasesError();
|
||||
throw NoReleasesError(note: tr('gitlabSourceNote'));
|
||||
}
|
||||
}
|
||||
return apkDetailsList.first;
|
||||
|
@ -4,6 +4,7 @@ import 'package:html/parser.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:obtainium/components/generated_form.dart';
|
||||
import 'package:obtainium/custom_errors.dart';
|
||||
import 'package:obtainium/providers/apps_provider.dart';
|
||||
import 'package:obtainium/providers/source_provider.dart';
|
||||
|
||||
String ensureAbsoluteUrl(String ambiguousUrl, Uri referenceAbsoluteUrl) {
|
||||
@ -94,6 +95,10 @@ class HTML extends AppSource {
|
||||
label: tr('sortByFileNamesNotLinks'))
|
||||
],
|
||||
[GeneratedFormSwitch('reverseSort', label: tr('reverseSort'))],
|
||||
[
|
||||
GeneratedFormSwitch('supportFixedAPKURL',
|
||||
defaultValue: true, label: tr('supportFixedAPKURL')),
|
||||
],
|
||||
[
|
||||
GeneratedFormTextField('customLinkFilterRegex',
|
||||
label: tr('customLinkFilterRegex'),
|
||||
@ -140,7 +145,7 @@ class HTML extends AppSource {
|
||||
]
|
||||
];
|
||||
overrideVersionDetectionFormDefault('noVersionDetection',
|
||||
disableStandard: true, disableRelDate: true);
|
||||
disableStandard: false, disableRelDate: true);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -170,7 +175,15 @@ class HTML extends AppSource {
|
||||
List<String> allLinks = html
|
||||
.querySelectorAll('a')
|
||||
.map((element) => element.attributes['href'] ?? '')
|
||||
.where((element) => element.isNotEmpty)
|
||||
.toList();
|
||||
if (allLinks.isEmpty) {
|
||||
allLinks = RegExp(
|
||||
r'(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?')
|
||||
.allMatches(res.body)
|
||||
.map((match) => match.group(0)!)
|
||||
.toList();
|
||||
}
|
||||
List<String> links = [];
|
||||
if ((additionalSettings['intermediateLinkRegex'] as String?)
|
||||
?.isNotEmpty ==
|
||||
@ -214,12 +227,17 @@ class HTML extends AppSource {
|
||||
throw NoReleasesError();
|
||||
}
|
||||
var rel = links.last;
|
||||
String? version = rel.hashCode.toString();
|
||||
String? version;
|
||||
if (additionalSettings['supportFixedAPKURL'] != true) {
|
||||
version = rel.hashCode.toString();
|
||||
}
|
||||
var versionExtractionRegEx =
|
||||
additionalSettings['versionExtractionRegEx'] as String?;
|
||||
if (versionExtractionRegEx?.isNotEmpty == true) {
|
||||
var match = RegExp(versionExtractionRegEx!).allMatches(
|
||||
res.body.split('\r\n').join('\n').split('\n').join('\\n'));
|
||||
additionalSettings['versionExtractWholePage'] == true
|
||||
? res.body.split('\r\n').join('\n').split('\n').join('\\n')
|
||||
: rel);
|
||||
if (match.isEmpty) {
|
||||
throw NoVersionError();
|
||||
}
|
||||
@ -233,9 +251,9 @@ class HTML extends AppSource {
|
||||
throw NoVersionError();
|
||||
}
|
||||
}
|
||||
List<String> apkUrls =
|
||||
[rel].map((e) => ensureAbsoluteUrl(e, uri)).toList();
|
||||
return APKDetails(version!, apkUrls.map((e) => MapEntry(e, e)).toList(),
|
||||
rel = ensureAbsoluteUrl(rel, uri);
|
||||
version ??= (await checkDownloadHash(rel)).toString();
|
||||
return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
|
||||
AppNames(uri.host, tr('app')));
|
||||
} else {
|
||||
throw getObtainiumHttpError(res);
|
||||
|
@ -89,11 +89,11 @@ class Uptodown extends AppSource {
|
||||
throw getObtainiumHttpError(res);
|
||||
}
|
||||
var html = parse(res.body);
|
||||
var finalUrl =
|
||||
(html.querySelector('.post-download')?.attributes['data-url']);
|
||||
if (finalUrl == null) {
|
||||
var finalUrlKey =
|
||||
html.querySelector('.post-download')?.attributes['data-url'];
|
||||
if (finalUrlKey == null) {
|
||||
throw NoAPKError();
|
||||
}
|
||||
return finalUrl;
|
||||
return 'https://dw.$host/dwn/$finalUrlKey';
|
||||
}
|
||||
}
|
||||
|
@ -27,21 +27,16 @@ class GeneratedFormTextField extends GeneratedFormItem {
|
||||
late bool password;
|
||||
late TextInputType? textInputType;
|
||||
|
||||
GeneratedFormTextField(String key,
|
||||
{String label = 'Input',
|
||||
List<Widget> belowWidgets = const [],
|
||||
String defaultValue = '',
|
||||
List<String? Function(String? value)> additionalValidators = const [],
|
||||
GeneratedFormTextField(super.key,
|
||||
{super.label,
|
||||
super.belowWidgets,
|
||||
String super.defaultValue = '',
|
||||
List<String? Function(String? value)> super.additionalValidators = const [],
|
||||
this.required = true,
|
||||
this.max = 1,
|
||||
this.hint,
|
||||
this.password = false,
|
||||
this.textInputType})
|
||||
: super(key,
|
||||
label: label,
|
||||
belowWidgets: belowWidgets,
|
||||
defaultValue: defaultValue,
|
||||
additionalValidators: additionalValidators);
|
||||
this.textInputType});
|
||||
|
||||
@override
|
||||
String ensureType(val) {
|
||||
@ -54,18 +49,14 @@ class GeneratedFormDropdown extends GeneratedFormItem {
|
||||
List<String>? disabledOptKeys;
|
||||
|
||||
GeneratedFormDropdown(
|
||||
String key,
|
||||
super.key,
|
||||
this.opts, {
|
||||
String label = 'Input',
|
||||
List<Widget> belowWidgets = const [],
|
||||
String defaultValue = '',
|
||||
super.label,
|
||||
super.belowWidgets,
|
||||
String super.defaultValue = '',
|
||||
this.disabledOptKeys,
|
||||
List<String? Function(String? value)> additionalValidators = const [],
|
||||
}) : super(key,
|
||||
label: label,
|
||||
belowWidgets: belowWidgets,
|
||||
defaultValue: defaultValue,
|
||||
additionalValidators: additionalValidators);
|
||||
List<String? Function(String? value)> super.additionalValidators = const [],
|
||||
});
|
||||
|
||||
@override
|
||||
String ensureType(val) {
|
||||
@ -75,16 +66,12 @@ class GeneratedFormDropdown extends GeneratedFormItem {
|
||||
|
||||
class GeneratedFormSwitch extends GeneratedFormItem {
|
||||
GeneratedFormSwitch(
|
||||
String key, {
|
||||
String label = 'Input',
|
||||
List<Widget> belowWidgets = const [],
|
||||
bool defaultValue = false,
|
||||
List<String? Function(bool value)> additionalValidators = const [],
|
||||
}) : super(key,
|
||||
label: label,
|
||||
belowWidgets: belowWidgets,
|
||||
defaultValue: defaultValue,
|
||||
additionalValidators: additionalValidators);
|
||||
super.key, {
|
||||
super.label,
|
||||
super.belowWidgets,
|
||||
bool super.defaultValue = false,
|
||||
List<String? Function(bool value)> super.additionalValidators = const [],
|
||||
});
|
||||
|
||||
@override
|
||||
bool ensureType(val) {
|
||||
@ -98,22 +85,17 @@ class GeneratedFormTagInput extends GeneratedFormItem {
|
||||
late WrapAlignment alignment;
|
||||
late String emptyMessage;
|
||||
late bool showLabelWhenNotEmpty;
|
||||
GeneratedFormTagInput(String key,
|
||||
{String label = 'Input',
|
||||
List<Widget> belowWidgets = const [],
|
||||
Map<String, MapEntry<int, bool>> defaultValue = const {},
|
||||
GeneratedFormTagInput(super.key,
|
||||
{super.label,
|
||||
super.belowWidgets,
|
||||
Map<String, MapEntry<int, bool>> super.defaultValue = const {},
|
||||
List<String? Function(Map<String, MapEntry<int, bool>> value)>
|
||||
additionalValidators = const [],
|
||||
super.additionalValidators = const [],
|
||||
this.deleteConfirmationMessage,
|
||||
this.singleSelect = false,
|
||||
this.alignment = WrapAlignment.start,
|
||||
this.emptyMessage = 'Input',
|
||||
this.showLabelWhenNotEmpty = true})
|
||||
: super(key,
|
||||
label: label,
|
||||
belowWidgets: belowWidgets,
|
||||
defaultValue: defaultValue,
|
||||
additionalValidators: additionalValidators);
|
||||
this.showLabelWhenNotEmpty = true});
|
||||
|
||||
@override
|
||||
Map<String, MapEntry<int, bool>> ensureType(val) {
|
||||
|
@ -34,7 +34,9 @@ class CredsNeededError extends ObtainiumError {
|
||||
}
|
||||
|
||||
class NoReleasesError extends ObtainiumError {
|
||||
NoReleasesError() : super(tr('noReleaseFound'));
|
||||
NoReleasesError({String? note})
|
||||
: super(
|
||||
'${tr('noReleaseFound')}${note?.isNotEmpty == true ? '\n\n$note' : ''}');
|
||||
}
|
||||
|
||||
class NoAPKError extends ObtainiumError {
|
||||
|
@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart';
|
||||
// ignore: implementation_imports
|
||||
import 'package:easy_localization/src/localization.dart';
|
||||
|
||||
const String currentVersion = '0.14.30';
|
||||
const String currentVersion = '0.14.37';
|
||||
const String currentReleaseTag =
|
||||
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
|
||||
|
||||
@ -40,9 +40,14 @@ List<MapEntry<Locale, String>> supportedLocales = const [
|
||||
MapEntry(Locale('bs'), 'Bosanski'),
|
||||
MapEntry(Locale('pt'), 'Brasileiro'),
|
||||
MapEntry(Locale('cs'), 'Česky'),
|
||||
MapEntry(Locale('sv'), 'Svenska'),
|
||||
MapEntry(Locale('nl'), 'Nederlands'),
|
||||
MapEntry(Locale('vi'), 'Tiếng Việt'),
|
||||
MapEntry(Locale('tr'), 'Türkçe'),
|
||||
];
|
||||
const fallbackLocale = Locale('en');
|
||||
const localeDir = 'assets/translations';
|
||||
var fdroid = false;
|
||||
|
||||
final globalNavigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
@ -131,20 +136,22 @@ class _ObtainiumState extends State<Obtainium> {
|
||||
logs.add('This is the first ever run of Obtainium.');
|
||||
// If this is the first run, ask for notification permissions and add Obtainium to the Apps list
|
||||
Permission.notification.request();
|
||||
appsProvider.saveApps([
|
||||
App(
|
||||
obtainiumId,
|
||||
'https://github.com/ImranR98/Obtainium',
|
||||
'ImranR98',
|
||||
'Obtainium',
|
||||
currentReleaseTag,
|
||||
currentReleaseTag,
|
||||
[],
|
||||
0,
|
||||
{'includePrereleases': true},
|
||||
null,
|
||||
false)
|
||||
], onlyIfExists: false);
|
||||
if (!fdroid) {
|
||||
appsProvider.saveApps([
|
||||
App(
|
||||
obtainiumId,
|
||||
'https://github.com/ImranR98/Obtainium',
|
||||
'ImranR98',
|
||||
'Obtainium',
|
||||
currentReleaseTag,
|
||||
currentReleaseTag,
|
||||
[],
|
||||
0,
|
||||
{'includePrereleases': true},
|
||||
null,
|
||||
false)
|
||||
], onlyIfExists: false);
|
||||
}
|
||||
}
|
||||
if (!supportedLocales
|
||||
.map((e) => e.key.languageCode)
|
||||
|
6
lib/main_fdroid.dart
Normal file
6
lib/main_fdroid.dart
Normal file
@ -0,0 +1,6 @@
|
||||
import 'main.dart' as m;
|
||||
|
||||
void main() async {
|
||||
m.fdroid = true;
|
||||
m.main();
|
||||
}
|
@ -21,10 +21,10 @@ class AddAppPage extends StatefulWidget {
|
||||
const AddAppPage({super.key});
|
||||
|
||||
@override
|
||||
State<AddAppPage> createState() => _AddAppPageState();
|
||||
State<AddAppPage> createState() => AddAppPageState();
|
||||
}
|
||||
|
||||
class _AddAppPageState extends State<AddAppPage> {
|
||||
class AddAppPageState extends State<AddAppPage> {
|
||||
bool gettingAppInfo = false;
|
||||
bool searching = false;
|
||||
|
||||
@ -36,9 +36,62 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
bool additionalSettingsValid = true;
|
||||
bool inferAppIdIfOptional = true;
|
||||
List<String> pickedCategories = [];
|
||||
int searchnum = 0;
|
||||
int urlInputKey = 0;
|
||||
SourceProvider sourceProvider = SourceProvider();
|
||||
|
||||
linkFn(String input) {
|
||||
try {
|
||||
if (input.isEmpty) {
|
||||
throw UnsupportedURLError();
|
||||
}
|
||||
sourceProvider.getSource(input);
|
||||
changeUserInput(input, true, false, updateUrlInput: true);
|
||||
} catch (e) {
|
||||
showError(e, context);
|
||||
}
|
||||
}
|
||||
|
||||
changeUserInput(String input, bool valid, bool isBuilding,
|
||||
{bool updateUrlInput = false}) {
|
||||
userInput = input;
|
||||
if (!isBuilding) {
|
||||
setState(() {
|
||||
if (updateUrlInput) {
|
||||
urlInputKey++;
|
||||
}
|
||||
var prevHost = pickedSource?.host;
|
||||
try {
|
||||
var naturalSource =
|
||||
valid ? sourceProvider.getSource(userInput) : null;
|
||||
if (naturalSource != null &&
|
||||
naturalSource.runtimeType.toString() !=
|
||||
HTML().runtimeType.toString()) {
|
||||
// If input has changed to match a regular source, reset the override
|
||||
pickedSourceOverride = null;
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
var source = valid
|
||||
? sourceProvider.getSource(userInput,
|
||||
overrideSource: pickedSourceOverride)
|
||||
: null;
|
||||
if (pickedSource.runtimeType != source.runtimeType ||
|
||||
(prevHost != null && prevHost != source?.host)) {
|
||||
pickedSource = source;
|
||||
additionalSettings = source != null
|
||||
? getDefaultValuesFromFormItems(
|
||||
source.combinedAppSpecificSettingFormItems)
|
||||
: {};
|
||||
additionalSettingsValid = source != null
|
||||
? !sourceProvider.ifRequiredAppSpecificSettingsExist(source)
|
||||
: true;
|
||||
inferAppIdIfOptional = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
AppsProvider appsProvider = context.read<AppsProvider>();
|
||||
@ -48,47 +101,6 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
|
||||
bool doingSomething = gettingAppInfo || searching;
|
||||
|
||||
changeUserInput(String input, bool valid, bool isBuilding,
|
||||
{bool isSearch = false}) {
|
||||
userInput = input;
|
||||
if (!isBuilding) {
|
||||
setState(() {
|
||||
if (isSearch) {
|
||||
searchnum++;
|
||||
}
|
||||
var prevHost = pickedSource?.host;
|
||||
try {
|
||||
var naturalSource =
|
||||
valid ? sourceProvider.getSource(userInput) : null;
|
||||
if (naturalSource != null &&
|
||||
naturalSource.runtimeType.toString() !=
|
||||
HTML().runtimeType.toString()) {
|
||||
// If input has changed to match a regular source, reset the override
|
||||
pickedSourceOverride = null;
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
var source = valid
|
||||
? sourceProvider.getSource(userInput,
|
||||
overrideSource: pickedSourceOverride)
|
||||
: null;
|
||||
if (pickedSource.runtimeType != source.runtimeType ||
|
||||
(prevHost != null && prevHost != source?.host)) {
|
||||
pickedSource = source;
|
||||
additionalSettings = source != null
|
||||
? getDefaultValuesFromFormItems(
|
||||
source.combinedAppSpecificSettingFormItems)
|
||||
: {};
|
||||
additionalSettingsValid = source != null
|
||||
? !sourceProvider.ifRequiredAppSpecificSettingsExist(source)
|
||||
: true;
|
||||
inferAppIdIfOptional = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> getTrackOnlyConfirmationIfNeeded(bool userPickedTrackOnly,
|
||||
{bool ignoreHideSetting = false}) async {
|
||||
var useTrackOnly = userPickedTrackOnly || pickedSource!.enforceTrackOnly;
|
||||
@ -205,7 +217,7 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: GeneratedForm(
|
||||
key: Key(searchnum.toString()),
|
||||
key: Key(urlInputKey.toString()),
|
||||
items: [
|
||||
[
|
||||
GeneratedFormTextField('appSourceURL',
|
||||
@ -254,57 +266,79 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
],
|
||||
);
|
||||
|
||||
runSearch() async {
|
||||
runSearch({bool filtered = true}) async {
|
||||
setState(() {
|
||||
searching = true;
|
||||
});
|
||||
var sourceStrings = <String, List<String>>{};
|
||||
sourceProvider.sources
|
||||
.where((e) => e.canSearch && !e.excludeFromMassSearch)
|
||||
.forEach((s) {
|
||||
sourceStrings[s.name] = [s.name];
|
||||
});
|
||||
try {
|
||||
var results = await Future.wait(sourceProvider.sources
|
||||
.where((e) => e.canSearch && !e.excludeFromMassSearch)
|
||||
.map((e) async {
|
||||
try {
|
||||
return await e.search(searchQuery);
|
||||
} catch (err) {
|
||||
if (err is! CredsNeededError) {
|
||||
rethrow;
|
||||
} else {
|
||||
return <String, List<String>>{};
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// .then((results) async {
|
||||
// Interleave results instead of simple reduce
|
||||
Map<String, List<String>> res = {};
|
||||
var si = 0;
|
||||
var done = false;
|
||||
while (!done) {
|
||||
done = true;
|
||||
for (var r in results) {
|
||||
if (r.length > si) {
|
||||
done = false;
|
||||
res.addEntries([r.entries.elementAt(si)]);
|
||||
}
|
||||
}
|
||||
si++;
|
||||
}
|
||||
if (res.isEmpty) {
|
||||
throw ObtainiumError(tr('noResults'));
|
||||
}
|
||||
List<String>? selectedUrls = res.isEmpty
|
||||
? []
|
||||
// ignore: use_build_context_synchronously
|
||||
: await showDialog<List<String>?>(
|
||||
var searchSources = await showDialog<List<String>?>(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return UrlSelectionModal(
|
||||
urlsWithDescriptions: res,
|
||||
selectedByDefault: false,
|
||||
onlyOneSelectionAllowed: true,
|
||||
return SelectionModal(
|
||||
title: tr('selectX', args: [plural('source', 2)]),
|
||||
entries: sourceStrings,
|
||||
selectedByDefault: true,
|
||||
onlyOneSelectionAllowed: false,
|
||||
titlesAreLinks: false,
|
||||
);
|
||||
});
|
||||
if (selectedUrls != null && selectedUrls.isNotEmpty) {
|
||||
changeUserInput(selectedUrls[0], true, false, isSearch: true);
|
||||
}) ??
|
||||
[];
|
||||
if (searchSources.isNotEmpty) {
|
||||
var results = await Future.wait(sourceProvider.sources
|
||||
.where((e) => searchSources.contains(e.name))
|
||||
.map((e) async {
|
||||
try {
|
||||
return await e.search(searchQuery);
|
||||
} catch (err) {
|
||||
if (err is! CredsNeededError) {
|
||||
rethrow;
|
||||
} else {
|
||||
err.unexpected = true;
|
||||
showError(err, context);
|
||||
return <String, List<String>>{};
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// .then((results) async {
|
||||
// Interleave results instead of simple reduce
|
||||
Map<String, List<String>> res = {};
|
||||
var si = 0;
|
||||
var done = false;
|
||||
while (!done) {
|
||||
done = true;
|
||||
for (var r in results) {
|
||||
if (r.length > si) {
|
||||
done = false;
|
||||
res.addEntries([r.entries.elementAt(si)]);
|
||||
}
|
||||
}
|
||||
si++;
|
||||
}
|
||||
if (res.isEmpty) {
|
||||
throw ObtainiumError(tr('noResults'));
|
||||
}
|
||||
List<String>? selectedUrls = res.isEmpty
|
||||
? []
|
||||
// ignore: use_build_context_synchronously
|
||||
: await showDialog<List<String>?>(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return SelectionModal(
|
||||
entries: res,
|
||||
selectedByDefault: false,
|
||||
onlyOneSelectionAllowed: true,
|
||||
);
|
||||
});
|
||||
if (selectedUrls != null && selectedUrls.isNotEmpty) {
|
||||
changeUserInput(selectedUrls[0], true, false, updateUrlInput: true);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
showError(e, context);
|
||||
@ -470,23 +504,21 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
...sourceProvider.sources
|
||||
.map((e) => GestureDetector(
|
||||
onTap: e.host != null
|
||||
? () {
|
||||
launchUrlString('https://${e.host}',
|
||||
mode: LaunchMode.externalApplication);
|
||||
}
|
||||
: null,
|
||||
child: Text(
|
||||
'${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}',
|
||||
style: TextStyle(
|
||||
decoration: e.host != null
|
||||
? TextDecoration.underline
|
||||
: TextDecoration.none,
|
||||
fontStyle: FontStyle.italic),
|
||||
)))
|
||||
.toList()
|
||||
...sourceProvider.sources.map((e) => GestureDetector(
|
||||
onTap: e.host != null
|
||||
? () {
|
||||
launchUrlString('https://${e.host}',
|
||||
mode: LaunchMode.externalApplication);
|
||||
}
|
||||
: null,
|
||||
child: Text(
|
||||
'${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}',
|
||||
style: TextStyle(
|
||||
decoration: e.host != null
|
||||
? TextDecoration.underline
|
||||
: TextDecoration.none,
|
||||
fontStyle: FontStyle.italic),
|
||||
)))
|
||||
]);
|
||||
|
||||
return Scaffold(
|
||||
|
@ -145,6 +145,29 @@ class _AppPageState extends State<AppPage> {
|
||||
appsProvider.saveApps([app.app]);
|
||||
}
|
||||
}),
|
||||
if (app?.app.additionalSettings['about'] is String &&
|
||||
app?.app.additionalSettings['about'].isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 48,
|
||||
),
|
||||
GestureDetector(
|
||||
onLongPress: () {
|
||||
Clipboard.setData(ClipboardData(
|
||||
text: app?.app.additionalSettings['about'] ?? ''));
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text(tr('copiedToClipboard')),
|
||||
));
|
||||
},
|
||||
child: Text(
|
||||
app?.app.additionalSettings['about'],
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontStyle: FontStyle.italic),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@ -155,10 +178,13 @@ class _AppPageState extends State<AppPage> {
|
||||
const SizedBox(height: 20),
|
||||
app?.icon != null
|
||||
? Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
Image.memory(
|
||||
app!.icon!,
|
||||
height: 150,
|
||||
gaplessPlayback: true,
|
||||
GestureDetector(
|
||||
child: Image.memory(
|
||||
app!.icon!,
|
||||
height: 150,
|
||||
gaplessPlayback: true,
|
||||
),
|
||||
onTap: () => pm.openApp(app.app.id),
|
||||
)
|
||||
])
|
||||
: Container(),
|
||||
@ -463,15 +489,15 @@ class _AppPageState extends State<AppPage> {
|
||||
: null))
|
||||
],
|
||||
));
|
||||
|
||||
|
||||
appScreenAppBar() => AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
);
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: settingsProvider.showAppWebpage ? AppBar() : appScreenAppBar(),
|
||||
|
@ -503,7 +503,7 @@ class AppsPageState extends State<AppsPage> {
|
||||
.entries
|
||||
.map((e) =>
|
||||
((e.key / (listedApps[index].app.categories.length - 1))))
|
||||
.toList(),
|
||||
,
|
||||
1
|
||||
];
|
||||
if (stops.length == 2) {
|
||||
@ -522,7 +522,7 @@ class AppsPageState extends State<AppsPage> {
|
||||
.map((e) =>
|
||||
Color(settingsProvider.categories[e] ?? transparent)
|
||||
.withAlpha(255))
|
||||
.toList(),
|
||||
,
|
||||
Color(transparent)
|
||||
])),
|
||||
child: ListTile(
|
||||
@ -984,7 +984,7 @@ class AppsPageState extends State<AppsPage> {
|
||||
...sourceProvider.sources
|
||||
.map((e) =>
|
||||
MapEntry(e.runtimeType.toString(), e.name))
|
||||
.toList()
|
||||
|
||||
])
|
||||
]
|
||||
],
|
||||
|
@ -1,7 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:app_links/app_links.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:obtainium/custom_errors.dart';
|
||||
import 'package:obtainium/pages/add_app.dart';
|
||||
import 'package:obtainium/pages/apps.dart';
|
||||
import 'package:obtainium/pages/import_export.dart';
|
||||
@ -30,58 +34,119 @@ class _HomePageState extends State<HomePage> {
|
||||
bool isReversing = false;
|
||||
int prevAppCount = -1;
|
||||
bool prevIsLoading = true;
|
||||
late AppLinks _appLinks;
|
||||
StreamSubscription<Uri>? _linkSubscription;
|
||||
bool isLinkActivity = false;
|
||||
|
||||
List<NavigationPageItem> pages = [
|
||||
NavigationPageItem(tr('appsString'), Icons.apps,
|
||||
AppsPage(key: GlobalKey<AppsPageState>())),
|
||||
NavigationPageItem(tr('addApp'), Icons.add, const AddAppPage()),
|
||||
NavigationPageItem(
|
||||
tr('addApp'), Icons.add, AddAppPage(key: GlobalKey<AddAppPageState>())),
|
||||
NavigationPageItem(
|
||||
tr('importExport'), Icons.import_export, const ImportExportPage()),
|
||||
NavigationPageItem(tr('settings'), Icons.settings, const SettingsPage())
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initDeepLinks();
|
||||
}
|
||||
|
||||
Future<void> initDeepLinks() async {
|
||||
_appLinks = AppLinks();
|
||||
|
||||
goToAddApp(String data) async {
|
||||
switchToPage(1);
|
||||
while (
|
||||
(pages[1].widget.key as GlobalKey<AddAppPageState>?)?.currentState ==
|
||||
null) {
|
||||
await Future.delayed(const Duration(microseconds: 1));
|
||||
}
|
||||
(pages[1].widget.key as GlobalKey<AddAppPageState>?)
|
||||
?.currentState
|
||||
?.linkFn(data);
|
||||
}
|
||||
|
||||
interpretLink(Uri uri) async {
|
||||
isLinkActivity = true;
|
||||
var action = uri.host;
|
||||
var data = uri.path.length > 1 ? uri.path.substring(1) : "";
|
||||
try {
|
||||
if (action == 'add') {
|
||||
await goToAddApp(data);
|
||||
} else if (action == 'app') {
|
||||
await context
|
||||
.read<AppsProvider>()
|
||||
.import('{ "apps": [${Uri.decodeComponent(data)}] }');
|
||||
} else if (action == 'apps') {
|
||||
await context
|
||||
.read<AppsProvider>()
|
||||
.import('{ "apps": ${Uri.decodeComponent(data)} }');
|
||||
} else {
|
||||
throw ObtainiumError(tr('unknown'));
|
||||
}
|
||||
} catch (e) {
|
||||
showError(e, context);
|
||||
}
|
||||
}
|
||||
|
||||
// Check initial link if app was in cold state (terminated)
|
||||
final appLink = await _appLinks.getInitialAppLink();
|
||||
if (appLink != null) {
|
||||
await interpretLink(appLink);
|
||||
}
|
||||
|
||||
// Handle link when app is in warm state (front or background)
|
||||
_linkSubscription = _appLinks.uriLinkStream.listen((uri) async {
|
||||
await interpretLink(uri);
|
||||
});
|
||||
}
|
||||
|
||||
setIsReversing(int targetIndex) {
|
||||
bool reversing = selectedIndexHistory.isNotEmpty &&
|
||||
selectedIndexHistory.last > targetIndex;
|
||||
setState(() {
|
||||
isReversing = reversing;
|
||||
});
|
||||
}
|
||||
|
||||
switchToPage(int index) async {
|
||||
setIsReversing(index);
|
||||
if (index == 0) {
|
||||
while ((pages[0].widget.key as GlobalKey<AppsPageState>).currentState !=
|
||||
null) {
|
||||
// Avoid duplicate GlobalKey error
|
||||
await Future.delayed(const Duration(microseconds: 1));
|
||||
}
|
||||
setState(() {
|
||||
selectedIndexHistory.clear();
|
||||
});
|
||||
} else if (selectedIndexHistory.isEmpty ||
|
||||
(selectedIndexHistory.isNotEmpty &&
|
||||
selectedIndexHistory.last != index)) {
|
||||
setState(() {
|
||||
int existingInd = selectedIndexHistory.indexOf(index);
|
||||
if (existingInd >= 0) {
|
||||
selectedIndexHistory.removeAt(existingInd);
|
||||
}
|
||||
selectedIndexHistory.add(index);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
AppsProvider appsProvider = context.watch<AppsProvider>();
|
||||
SettingsProvider settingsProvider = context.watch<SettingsProvider>();
|
||||
|
||||
setIsReversing(int targetIndex) {
|
||||
bool reversing = selectedIndexHistory.isNotEmpty &&
|
||||
selectedIndexHistory.last > targetIndex;
|
||||
setState(() {
|
||||
isReversing = reversing;
|
||||
});
|
||||
}
|
||||
|
||||
switchToPage(int index) async {
|
||||
setIsReversing(index);
|
||||
if (index == 0) {
|
||||
while ((pages[0].widget.key as GlobalKey<AppsPageState>).currentState !=
|
||||
null) {
|
||||
// Avoid duplicate GlobalKey error
|
||||
await Future.delayed(const Duration(microseconds: 1));
|
||||
}
|
||||
setState(() {
|
||||
selectedIndexHistory.clear();
|
||||
});
|
||||
} else if (selectedIndexHistory.isEmpty ||
|
||||
(selectedIndexHistory.isNotEmpty &&
|
||||
selectedIndexHistory.last != index)) {
|
||||
setState(() {
|
||||
int existingInd = selectedIndexHistory.indexOf(index);
|
||||
if (existingInd >= 0) {
|
||||
selectedIndexHistory.removeAt(existingInd);
|
||||
}
|
||||
selectedIndexHistory.add(index);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!prevIsLoading &&
|
||||
prevAppCount >= 0 &&
|
||||
appsProvider.apps.length > prevAppCount &&
|
||||
selectedIndexHistory.isNotEmpty &&
|
||||
selectedIndexHistory.last == 1) {
|
||||
selectedIndexHistory.last == 1 &&
|
||||
!isLinkActivity) {
|
||||
switchToPage(0);
|
||||
}
|
||||
prevAppCount = appsProvider.apps.length;
|
||||
@ -129,6 +194,11 @@ class _HomePageState extends State<HomePage> {
|
||||
),
|
||||
),
|
||||
onWillPop: () async {
|
||||
if (isLinkActivity &&
|
||||
selectedIndexHistory.length == 1 &&
|
||||
selectedIndexHistory.last == 1) {
|
||||
return true;
|
||||
}
|
||||
setIsReversing(selectedIndexHistory.length >= 2
|
||||
? selectedIndexHistory.reversed.toList()[1]
|
||||
: 0);
|
||||
@ -143,4 +213,10 @@ class _HomePageState extends State<HomePage> {
|
||||
?.clearSelected();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_linkSubscription?.cancel();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import 'dart:io';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
||||
import 'package:obtainium/components/custom_app_bar.dart';
|
||||
import 'package:obtainium/components/generated_form.dart';
|
||||
import 'package:obtainium/components/generated_form_modal.dart';
|
||||
@ -105,7 +106,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
runObtainiumExport({bool pickOnly = false}) async {
|
||||
HapticFeedback.selectionClick();
|
||||
appsProvider
|
||||
.exportApps(
|
||||
.export(
|
||||
pickOnly:
|
||||
pickOnly || (await settingsProvider.getExportDir()) == null,
|
||||
sp: settingsProvider)
|
||||
@ -131,7 +132,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
} catch (e) {
|
||||
throw ObtainiumError(tr('invalidInput'));
|
||||
}
|
||||
appsProvider.importApps(data).then((value) {
|
||||
appsProvider.import(data).then((value) {
|
||||
var cats = settingsProvider.categories;
|
||||
appsProvider.apps.forEach((key, value) {
|
||||
for (var c in value.app.categories) {
|
||||
@ -142,7 +143,10 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
});
|
||||
appsProvider.addMissingCategories(settingsProvider);
|
||||
showMessage(
|
||||
tr('importedX', args: [plural('apps', value)]), context);
|
||||
'${tr('importedX', args: [
|
||||
plural('apps', value.key)
|
||||
])}${value.value ? ' + ${tr('settings')}' : ''}',
|
||||
context);
|
||||
});
|
||||
} else {
|
||||
// User canceled the picker
|
||||
@ -189,17 +193,29 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
items: [
|
||||
[
|
||||
GeneratedFormTextField('searchQuery',
|
||||
label: tr('searchQuery'))
|
||||
label: tr('searchQuery'),
|
||||
required: source.name != FDroidRepo().name)
|
||||
],
|
||||
...source.searchQuerySettingFormItems.map((e) => [e]),
|
||||
[
|
||||
GeneratedFormTextField('url',
|
||||
label: source.host != null
|
||||
? tr('overrideSource')
|
||||
: plural('url', 1).substring(2),
|
||||
defaultValue: source.host ?? '',
|
||||
required: true)
|
||||
],
|
||||
...source.searchQuerySettingFormItems.map((e) => [e])
|
||||
],
|
||||
);
|
||||
});
|
||||
if (values != null &&
|
||||
(values['searchQuery'] as String?)?.isNotEmpty == true) {
|
||||
if (values != null) {
|
||||
setState(() {
|
||||
importInProgress = true;
|
||||
});
|
||||
if (values['url'] != source.host) {
|
||||
source = sourceProvider.getSource(values['url'],
|
||||
overrideSource: source.runtimeType.toString());
|
||||
}
|
||||
var urlsWithDescriptions = await source
|
||||
.search(values['searchQuery'] as String, querySettings: values);
|
||||
if (urlsWithDescriptions.isNotEmpty) {
|
||||
@ -208,13 +224,14 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
await showDialog<List<String>?>(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return UrlSelectionModal(
|
||||
urlsWithDescriptions: urlsWithDescriptions,
|
||||
return SelectionModal(
|
||||
entries: urlsWithDescriptions,
|
||||
selectedByDefault: false,
|
||||
);
|
||||
});
|
||||
if (selectedUrls != null && selectedUrls.isNotEmpty) {
|
||||
var errors = await appsProvider.addAppsByURL(selectedUrls);
|
||||
var errors = await appsProvider.addAppsByURL(selectedUrls,
|
||||
sourceOverride: source);
|
||||
if (errors.isEmpty) {
|
||||
// ignore: use_build_context_synchronously
|
||||
showMessage(
|
||||
@ -268,8 +285,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
await showDialog<List<String>?>(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return UrlSelectionModal(
|
||||
urlsWithDescriptions: urlsWithDescriptions);
|
||||
return SelectionModal(entries: urlsWithDescriptions);
|
||||
});
|
||||
if (selectedUrls != null) {
|
||||
var errors = await appsProvider.addAppsByURL(selectedUrls);
|
||||
@ -299,6 +315,11 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
});
|
||||
}
|
||||
|
||||
var sourceStrings = <String, List<String>>{};
|
||||
sourceProvider.sources.where((e) => e.canSearch).forEach((s) {
|
||||
sourceStrings[s.name] = [s.name];
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
body: CustomScrollView(slivers: <Widget>[
|
||||
@ -370,6 +391,14 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
defaultValue: settingsProvider
|
||||
.autoExportOnChanges,
|
||||
)
|
||||
],
|
||||
[
|
||||
GeneratedFormSwitch(
|
||||
'exportSettings',
|
||||
label: tr('includeSettings'),
|
||||
defaultValue: settingsProvider
|
||||
.exportSettings,
|
||||
)
|
||||
]
|
||||
],
|
||||
onValueChanges:
|
||||
@ -382,6 +411,12 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
'autoExportOnChanges'] ==
|
||||
true;
|
||||
}
|
||||
if (value['exportSettings'] !=
|
||||
null) {
|
||||
settingsProvider.exportSettings =
|
||||
value['exportSettings'] ==
|
||||
true;
|
||||
}
|
||||
}
|
||||
}),
|
||||
],
|
||||
@ -408,6 +443,54 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
const Divider(
|
||||
height: 32,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextButton(
|
||||
onPressed: importInProgress
|
||||
? null
|
||||
: () async {
|
||||
var searchSourceName =
|
||||
await showDialog<
|
||||
List<String>?>(
|
||||
context: context,
|
||||
builder:
|
||||
(BuildContext
|
||||
ctx) {
|
||||
return SelectionModal(
|
||||
title: tr(
|
||||
'selectX',
|
||||
args: [
|
||||
tr('source')
|
||||
]),
|
||||
entries:
|
||||
sourceStrings,
|
||||
selectedByDefault:
|
||||
false,
|
||||
onlyOneSelectionAllowed:
|
||||
true,
|
||||
titlesAreLinks:
|
||||
false,
|
||||
);
|
||||
}) ??
|
||||
[];
|
||||
var searchSource =
|
||||
sourceProvider.sources
|
||||
.where((e) =>
|
||||
searchSourceName
|
||||
.contains(
|
||||
e.name))
|
||||
.toList();
|
||||
if (searchSource.isNotEmpty) {
|
||||
runSourceSearch(
|
||||
searchSource[0]);
|
||||
}
|
||||
},
|
||||
child: Text(tr('searchX',
|
||||
args: [tr('source')])))),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextButton(
|
||||
onPressed:
|
||||
importInProgress ? null : urlListImport,
|
||||
@ -423,39 +506,19 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
)),
|
||||
],
|
||||
),
|
||||
...sourceProvider.sources
|
||||
.where((element) => element.canSearch)
|
||||
.map((source) => Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
TextButton(
|
||||
onPressed: importInProgress
|
||||
? null
|
||||
: () {
|
||||
runSourceSearch(source);
|
||||
},
|
||||
child: Text(
|
||||
tr('searchX', args: [source.name])))
|
||||
]))
|
||||
.toList(),
|
||||
...sourceProvider.massUrlSources
|
||||
.map((source) => Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
TextButton(
|
||||
onPressed: importInProgress
|
||||
? null
|
||||
: () {
|
||||
runMassSourceImport(source);
|
||||
},
|
||||
child: Text(
|
||||
tr('importX', args: [source.name])))
|
||||
]))
|
||||
.toList(),
|
||||
...sourceProvider.massUrlSources.map((source) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
TextButton(
|
||||
onPressed: importInProgress
|
||||
? null
|
||||
: () {
|
||||
runMassSourceImport(source);
|
||||
},
|
||||
child: Text(
|
||||
tr('importX', args: [source.name])))
|
||||
])),
|
||||
const Spacer(),
|
||||
const Divider(
|
||||
height: 32,
|
||||
@ -517,7 +580,7 @@ class _ImportErrorDialogState extends State<ImportErrorDialog> {
|
||||
style: const TextStyle(fontStyle: FontStyle.italic),
|
||||
)
|
||||
]);
|
||||
}).toList()
|
||||
})
|
||||
]),
|
||||
actions: [
|
||||
TextButton(
|
||||
@ -531,112 +594,171 @@ class _ImportErrorDialogState extends State<ImportErrorDialog> {
|
||||
}
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class UrlSelectionModal extends StatefulWidget {
|
||||
UrlSelectionModal(
|
||||
class SelectionModal extends StatefulWidget {
|
||||
SelectionModal(
|
||||
{super.key,
|
||||
required this.urlsWithDescriptions,
|
||||
required this.entries,
|
||||
this.selectedByDefault = true,
|
||||
this.onlyOneSelectionAllowed = false});
|
||||
this.onlyOneSelectionAllowed = false,
|
||||
this.titlesAreLinks = true,
|
||||
this.title});
|
||||
|
||||
Map<String, List<String>> urlsWithDescriptions;
|
||||
String? title;
|
||||
Map<String, List<String>> entries;
|
||||
bool selectedByDefault;
|
||||
bool onlyOneSelectionAllowed;
|
||||
bool titlesAreLinks;
|
||||
|
||||
@override
|
||||
State<UrlSelectionModal> createState() => _UrlSelectionModalState();
|
||||
State<SelectionModal> createState() => _SelectionModalState();
|
||||
}
|
||||
|
||||
class _UrlSelectionModalState extends State<UrlSelectionModal> {
|
||||
Map<MapEntry<String, List<String>>, bool> urlWithDescriptionSelections = {};
|
||||
class _SelectionModalState extends State<SelectionModal> {
|
||||
Map<MapEntry<String, List<String>>, bool> entrySelections = {};
|
||||
String filterRegex = '';
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
for (var url in widget.urlsWithDescriptions.entries) {
|
||||
urlWithDescriptionSelections.putIfAbsent(url,
|
||||
for (var url in widget.entries.entries) {
|
||||
entrySelections.putIfAbsent(url,
|
||||
() => widget.selectedByDefault && !widget.onlyOneSelectionAllowed);
|
||||
}
|
||||
if (widget.selectedByDefault && widget.onlyOneSelectionAllowed) {
|
||||
selectOnlyOne(widget.urlsWithDescriptions.entries.first.key);
|
||||
selectOnlyOne(widget.entries.entries.first.key);
|
||||
}
|
||||
}
|
||||
|
||||
selectOnlyOne(String url) {
|
||||
for (var uwd in urlWithDescriptionSelections.keys) {
|
||||
urlWithDescriptionSelections[uwd] = uwd.key == url;
|
||||
for (var e in entrySelections.keys) {
|
||||
entrySelections[e] = e.key == url;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Map<MapEntry<String, List<String>>, bool> filteredEntrySelections = {};
|
||||
entrySelections.forEach((key, value) {
|
||||
var searchableText = key.value.isEmpty ? key.key : key.value[0];
|
||||
if (filterRegex.isEmpty || RegExp(filterRegex).hasMatch(searchableText)) {
|
||||
filteredEntrySelections.putIfAbsent(key, () => value);
|
||||
}
|
||||
});
|
||||
if (filterRegex.isNotEmpty && filteredEntrySelections.isEmpty) {
|
||||
entrySelections.forEach((key, value) {
|
||||
var searchableText = key.value.isEmpty ? key.key : key.value[0];
|
||||
if (filterRegex.isEmpty ||
|
||||
RegExp(filterRegex, caseSensitive: false)
|
||||
.hasMatch(searchableText)) {
|
||||
filteredEntrySelections.putIfAbsent(key, () => value);
|
||||
}
|
||||
});
|
||||
}
|
||||
return AlertDialog(
|
||||
scrollable: true,
|
||||
title: Text(
|
||||
widget.onlyOneSelectionAllowed ? tr('selectURL') : tr('selectURLs')),
|
||||
title: Text(widget.title ?? tr('pick')),
|
||||
content: Column(children: [
|
||||
...urlWithDescriptionSelections.keys.map((urlWithD) {
|
||||
GeneratedForm(
|
||||
items: [
|
||||
[
|
||||
GeneratedFormTextField('filter',
|
||||
label: tr('filter'),
|
||||
required: false,
|
||||
additionalValidators: [
|
||||
(value) {
|
||||
return regExValidator(value);
|
||||
}
|
||||
])
|
||||
]
|
||||
],
|
||||
onValueChanges: (value, valid, isBuilding) {
|
||||
if (valid && !isBuilding) {
|
||||
if (value['filter'] != null) {
|
||||
setState(() {
|
||||
filterRegex = value['filter'];
|
||||
});
|
||||
}
|
||||
}
|
||||
}),
|
||||
...filteredEntrySelections.keys.map((entry) {
|
||||
selectThis(bool? value) {
|
||||
setState(() {
|
||||
value ??= false;
|
||||
if (value! && widget.onlyOneSelectionAllowed) {
|
||||
selectOnlyOne(urlWithD.key);
|
||||
selectOnlyOne(entry.key);
|
||||
} else {
|
||||
urlWithDescriptionSelections[urlWithD] = value!;
|
||||
entrySelections[entry] = value!;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var urlLink = GestureDetector(
|
||||
onTap: () {
|
||||
launchUrlString(urlWithD.key,
|
||||
mode: LaunchMode.externalApplication);
|
||||
},
|
||||
onTap: !widget.titlesAreLinks
|
||||
? null
|
||||
: () {
|
||||
launchUrlString(entry.key,
|
||||
mode: LaunchMode.externalApplication);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
urlWithD.value[0],
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
entry.value.isEmpty ? entry.key : entry.value[0],
|
||||
style: TextStyle(
|
||||
decoration: widget.titlesAreLinks
|
||||
? TextDecoration.underline
|
||||
: null,
|
||||
fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Text(
|
||||
Uri.parse(urlWithD.key).host,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline, fontSize: 12),
|
||||
)
|
||||
if (widget.titlesAreLinks)
|
||||
Text(
|
||||
Uri.parse(entry.key).host,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline, fontSize: 12),
|
||||
)
|
||||
],
|
||||
));
|
||||
|
||||
var descriptionText = Text(
|
||||
urlWithD.value[1].length > 128
|
||||
? '${urlWithD.value[1].substring(0, 128)}...'
|
||||
: urlWithD.value[1],
|
||||
style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12),
|
||||
);
|
||||
var descriptionText = entry.value.length <= 1
|
||||
? const SizedBox.shrink()
|
||||
: Text(
|
||||
entry.value[1].length > 128
|
||||
? '${entry.value[1].substring(0, 128)}...'
|
||||
: entry.value[1],
|
||||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic, fontSize: 12),
|
||||
);
|
||||
|
||||
var selectedUrlsWithDs = urlWithDescriptionSelections.entries
|
||||
.where((e) => e.value)
|
||||
.toList();
|
||||
var selectedEntries =
|
||||
entrySelections.entries.where((e) => e.value).toList();
|
||||
|
||||
var singleSelectTile = ListTile(
|
||||
title: urlLink,
|
||||
subtitle: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectOnlyOne(urlWithD.key);
|
||||
});
|
||||
},
|
||||
child: descriptionText,
|
||||
),
|
||||
leading: Radio<String>(
|
||||
value: urlWithD.key,
|
||||
groupValue: selectedUrlsWithDs.isEmpty
|
||||
title: GestureDetector(
|
||||
onTap: widget.titlesAreLinks
|
||||
? null
|
||||
: selectedUrlsWithDs.first.key.key,
|
||||
: () {
|
||||
selectThis(!(entrySelections[entry] ?? false));
|
||||
},
|
||||
child: urlLink,
|
||||
),
|
||||
subtitle: entry.value.length <= 1
|
||||
? null
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectOnlyOne(entry.key);
|
||||
});
|
||||
},
|
||||
child: descriptionText,
|
||||
),
|
||||
leading: Radio<String>(
|
||||
value: entry.key,
|
||||
groupValue: selectedEntries.isEmpty
|
||||
? null
|
||||
: selectedEntries.first.key.key,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
selectOnlyOne(urlWithD.key);
|
||||
selectOnlyOne(entry.key);
|
||||
});
|
||||
},
|
||||
),
|
||||
@ -644,7 +766,7 @@ class _UrlSelectionModalState extends State<UrlSelectionModal> {
|
||||
|
||||
var multiSelectTile = Row(children: [
|
||||
Checkbox(
|
||||
value: urlWithDescriptionSelections[urlWithD],
|
||||
value: entrySelections[entry],
|
||||
onChanged: (value) {
|
||||
selectThis(value);
|
||||
}),
|
||||
@ -659,14 +781,22 @@ class _UrlSelectionModalState extends State<UrlSelectionModal> {
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
urlLink,
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
selectThis(
|
||||
!(urlWithDescriptionSelections[urlWithD] ?? false));
|
||||
},
|
||||
child: descriptionText,
|
||||
onTap: widget.titlesAreLinks
|
||||
? null
|
||||
: () {
|
||||
selectThis(!(entrySelections[entry] ?? false));
|
||||
},
|
||||
child: urlLink,
|
||||
),
|
||||
entry.value.length <= 1
|
||||
? const SizedBox.shrink()
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
selectThis(!(entrySelections[entry] ?? false));
|
||||
},
|
||||
child: descriptionText,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
)
|
||||
@ -686,24 +816,18 @@ class _UrlSelectionModalState extends State<UrlSelectionModal> {
|
||||
},
|
||||
child: Text(tr('cancel'))),
|
||||
TextButton(
|
||||
onPressed:
|
||||
urlWithDescriptionSelections.values.where((b) => b).isEmpty
|
||||
? null
|
||||
: () {
|
||||
Navigator.of(context).pop(urlWithDescriptionSelections
|
||||
.entries
|
||||
.where((entry) => entry.value)
|
||||
.map((e) => e.key.key)
|
||||
.toList());
|
||||
},
|
||||
onPressed: entrySelections.values.where((b) => b).isEmpty
|
||||
? null
|
||||
: () {
|
||||
Navigator.of(context).pop(entrySelections.entries
|
||||
.where((entry) => entry.value)
|
||||
.map((e) => e.key.key)
|
||||
.toList());
|
||||
},
|
||||
child: Text(widget.onlyOneSelectionAllowed
|
||||
? tr('pick')
|
||||
: tr('importX', args: [
|
||||
plural(
|
||||
'url',
|
||||
urlWithDescriptionSelections.values
|
||||
.where((b) => b)
|
||||
.length)
|
||||
: tr('selectX', args: [
|
||||
entrySelections.values.where((b) => b).length.toString()
|
||||
])))
|
||||
],
|
||||
);
|
||||
|
@ -310,6 +310,23 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||
})
|
||||
],
|
||||
),
|
||||
height16,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(tr(
|
||||
'onlyCheckInstalledOrTrackOnlyApps'))),
|
||||
Switch(
|
||||
value: settingsProvider
|
||||
.onlyCheckInstalledOrTrackOnlyApps,
|
||||
onChanged: (value) {
|
||||
settingsProvider
|
||||
.onlyCheckInstalledOrTrackOnlyApps =
|
||||
value;
|
||||
})
|
||||
],
|
||||
),
|
||||
height32,
|
||||
Text(
|
||||
tr('sourceSpecific'),
|
||||
@ -535,7 +552,8 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||
onPressed: () {
|
||||
context.read<LogsProvider>().get().then((logs) {
|
||||
if (logs.isEmpty) {
|
||||
showMessage(ObtainiumError(tr('noLogs')), context);
|
||||
showMessage(
|
||||
ObtainiumError(tr('noLogs')), context);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
|
@ -6,6 +6,7 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:crypto/crypto.dart';
|
||||
|
||||
import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';
|
||||
import 'package:android_intent_plus/flag.dart';
|
||||
@ -139,6 +140,100 @@ List<MapEntry<String, int>> moveStrToEndMapEntryWithCount(
|
||||
return arr;
|
||||
}
|
||||
|
||||
Future<File> downloadFileWithRetry(
|
||||
String url, String fileNameNoExt, Function? onProgress, String destDir,
|
||||
{bool useExisting = true,
|
||||
Map<String, String>? headers,
|
||||
int retries = 3}) async {
|
||||
try {
|
||||
return await downloadFile(url, fileNameNoExt, onProgress, destDir,
|
||||
useExisting: useExisting, headers: headers);
|
||||
} catch (e) {
|
||||
if (retries > 0 && e is ClientException) {
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
return await downloadFileWithRetry(
|
||||
url, fileNameNoExt, onProgress, destDir,
|
||||
useExisting: useExisting, headers: headers, retries: (retries - 1));
|
||||
} else {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String hashListOfLists(List<List<int>> data) {
|
||||
var bytes = utf8.encode(jsonEncode(data));
|
||||
var digest = sha256.convert(bytes);
|
||||
var hash = digest.toString();
|
||||
return hash.hashCode.toString();
|
||||
}
|
||||
|
||||
Future<String> checkDownloadHash(String url,
|
||||
{int bytesToGrab = 1024, Map<String, String>? headers}) async {
|
||||
var req = Request('GET', Uri.parse(url));
|
||||
if (headers != null) {
|
||||
req.headers.addAll(headers);
|
||||
}
|
||||
req.headers[HttpHeaders.rangeHeader] = 'bytes=0-$bytesToGrab';
|
||||
var client = http.Client();
|
||||
var response = await client.send(req);
|
||||
if (response.statusCode < 200 || response.statusCode > 299) {
|
||||
throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError'));
|
||||
}
|
||||
List<List<int>> bytes = await response.stream.take(bytesToGrab).toList();
|
||||
return hashListOfLists(bytes);
|
||||
}
|
||||
|
||||
Future<File> downloadFile(
|
||||
String url, String fileNameNoExt, Function? onProgress, String destDir,
|
||||
{bool useExisting = true, Map<String, String>? headers}) async {
|
||||
var req = Request('GET', Uri.parse(url));
|
||||
if (headers != null) {
|
||||
req.headers.addAll(headers);
|
||||
}
|
||||
var client = http.Client();
|
||||
StreamedResponse response = await client.send(req);
|
||||
String ext =
|
||||
response.headers['content-disposition']?.split('.').last ?? 'apk';
|
||||
if (ext.endsWith('"') || ext.endsWith("other")) {
|
||||
ext = ext.substring(0, ext.length - 1);
|
||||
}
|
||||
if (url.toLowerCase().endsWith('.apk') && ext != 'apk') {
|
||||
ext = 'apk';
|
||||
}
|
||||
File downloadedFile = File('$destDir/$fileNameNoExt.$ext');
|
||||
if (!(downloadedFile.existsSync() && useExisting)) {
|
||||
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
||||
if (tempDownloadedFile.existsSync()) {
|
||||
tempDownloadedFile.deleteSync(recursive: true);
|
||||
}
|
||||
var length = response.contentLength;
|
||||
var received = 0;
|
||||
double? progress;
|
||||
var sink = tempDownloadedFile.openWrite();
|
||||
await response.stream.map((s) {
|
||||
received += s.length;
|
||||
progress = (length != null ? received / length * 100 : 30);
|
||||
if (onProgress != null) {
|
||||
onProgress(progress);
|
||||
}
|
||||
return s;
|
||||
}).pipe(sink);
|
||||
await sink.close();
|
||||
progress = null;
|
||||
if (onProgress != null) {
|
||||
onProgress(progress);
|
||||
}
|
||||
if (response.statusCode != 200) {
|
||||
tempDownloadedFile.deleteSync(recursive: true);
|
||||
throw response.reasonPhrase ?? tr('unexpectedError');
|
||||
}
|
||||
tempDownloadedFile.renameSync(downloadedFile.path);
|
||||
} else {
|
||||
client.close();
|
||||
}
|
||||
return downloadedFile;
|
||||
}
|
||||
|
||||
class AppsProvider with ChangeNotifier {
|
||||
// In memory App state (should always be kept in sync with local storage versions)
|
||||
Map<String, AppInMemory> apps = {};
|
||||
@ -192,77 +287,6 @@ class AppsProvider with ChangeNotifier {
|
||||
}();
|
||||
}
|
||||
|
||||
Future<File> downloadFileWithRetry(
|
||||
String url, String fileNameNoExt, Function? onProgress,
|
||||
{bool useExisting = true,
|
||||
Map<String, String>? headers,
|
||||
int retries = 3}) async {
|
||||
try {
|
||||
return await downloadFile(url, fileNameNoExt, onProgress,
|
||||
useExisting: useExisting, headers: headers);
|
||||
} catch (e) {
|
||||
if (retries > 0 && e is ClientException) {
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
return await downloadFileWithRetry(url, fileNameNoExt, onProgress,
|
||||
useExisting: useExisting, headers: headers, retries: (retries - 1));
|
||||
} else {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<File> downloadFile(
|
||||
String url, String fileNameNoExt, Function? onProgress,
|
||||
{bool useExisting = true, Map<String, String>? headers}) async {
|
||||
var destDir = APKDir.path;
|
||||
var req = Request('GET', Uri.parse(url));
|
||||
if (headers != null) {
|
||||
req.headers.addAll(headers);
|
||||
}
|
||||
var client = http.Client();
|
||||
StreamedResponse response = await client.send(req);
|
||||
String ext =
|
||||
response.headers['content-disposition']?.split('.').last ?? 'apk';
|
||||
if (ext.endsWith('"') || ext.endsWith("other")) {
|
||||
ext = ext.substring(0, ext.length - 1);
|
||||
}
|
||||
if (url.toLowerCase().endsWith('.apk') && ext != 'apk') {
|
||||
ext = 'apk';
|
||||
}
|
||||
File downloadedFile = File('$destDir/$fileNameNoExt.$ext');
|
||||
if (!(downloadedFile.existsSync() && useExisting)) {
|
||||
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
||||
if (tempDownloadedFile.existsSync()) {
|
||||
tempDownloadedFile.deleteSync(recursive: true);
|
||||
}
|
||||
var length = response.contentLength;
|
||||
var received = 0;
|
||||
double? progress;
|
||||
var sink = tempDownloadedFile.openWrite();
|
||||
await response.stream.map((s) {
|
||||
received += s.length;
|
||||
progress = (length != null ? received / length * 100 : 30);
|
||||
if (onProgress != null) {
|
||||
onProgress(progress);
|
||||
}
|
||||
return s;
|
||||
}).pipe(sink);
|
||||
await sink.close();
|
||||
progress = null;
|
||||
if (onProgress != null) {
|
||||
onProgress(progress);
|
||||
}
|
||||
if (response.statusCode != 200) {
|
||||
tempDownloadedFile.deleteSync(recursive: true);
|
||||
throw response.reasonPhrase ?? tr('unexpectedError');
|
||||
}
|
||||
tempDownloadedFile.renameSync(downloadedFile.path);
|
||||
} else {
|
||||
client.close();
|
||||
}
|
||||
return downloadedFile;
|
||||
}
|
||||
|
||||
Future<File> handleAPKIDChange(App app, PackageInfo? newInfo,
|
||||
File downloadedFile, String downloadUrl) async {
|
||||
// If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed
|
||||
@ -281,7 +305,8 @@ class AppsProvider with ChangeNotifier {
|
||||
'${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}');
|
||||
if (apps[originalAppId] != null) {
|
||||
await removeApps([originalAppId]);
|
||||
await saveApps([app], onlyIfExists: !isTempIdBool && !idChangeWasAllowed);
|
||||
await saveApps([app],
|
||||
onlyIfExists: !isTempIdBool && !idChangeWasAllowed);
|
||||
}
|
||||
}
|
||||
} else if (isTempIdBool) {
|
||||
@ -321,7 +346,7 @@ class AppsProvider with ChangeNotifier {
|
||||
notificationsProvider?.notify(notif);
|
||||
}
|
||||
prevProg = prog;
|
||||
});
|
||||
}, APKDir.path);
|
||||
// Set to 90 for remaining steps, will make null in 'finally'
|
||||
if (apps[app.id] != null) {
|
||||
apps[app.id]!.downloadProgress = -1;
|
||||
@ -716,9 +741,11 @@ class AppsProvider with ChangeNotifier {
|
||||
if (app?.app == null) {
|
||||
return false;
|
||||
}
|
||||
var naiveStandardVersionDetection = SourceProvider()
|
||||
.getSource(app!.app.url, overrideSource: app.app.overrideSource)
|
||||
.naiveStandardVersionDetection;
|
||||
var naiveStandardVersionDetection =
|
||||
app!.app.additionalSettings['naiveStandardVersionDetection'] == true ||
|
||||
SourceProvider()
|
||||
.getSource(app.app.url, overrideSource: app.app.overrideSource)
|
||||
.naiveStandardVersionDetection;
|
||||
return app.app.additionalSettings['trackOnly'] != true &&
|
||||
app.app.additionalSettings['versionDetection'] !=
|
||||
'releaseDateAsVersion' &&
|
||||
@ -739,9 +766,11 @@ class AppsProvider with ChangeNotifier {
|
||||
var versionDetectionIsStandard =
|
||||
app.additionalSettings['versionDetection'] ==
|
||||
'standardVersionDetection';
|
||||
var naiveStandardVersionDetection = SourceProvider()
|
||||
.getSource(app.url, overrideSource: app.overrideSource)
|
||||
.naiveStandardVersionDetection;
|
||||
var naiveStandardVersionDetection =
|
||||
app.additionalSettings['naiveStandardVersionDetection'] == true ||
|
||||
SourceProvider()
|
||||
.getSource(app.url, overrideSource: app.overrideSource)
|
||||
.naiveStandardVersionDetection;
|
||||
// FIRST, COMPARE THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE ONE IS NULL
|
||||
if (installedInfo == null && app.installedVersion != null && !trackOnly) {
|
||||
// App says it's installed but isn't really (and isn't track only) - set to not installed
|
||||
@ -945,7 +974,7 @@ class AppsProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
notifyListeners();
|
||||
exportApps(isAuto: true);
|
||||
export(isAuto: true);
|
||||
}
|
||||
|
||||
Future<void> removeApps(List<String> appIds) async {
|
||||
@ -967,7 +996,7 @@ class AppsProvider with ChangeNotifier {
|
||||
}
|
||||
if (appIds.isNotEmpty) {
|
||||
notifyListeners();
|
||||
exportApps(isAuto: true);
|
||||
export(isAuto: true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1055,12 +1084,21 @@ class AppsProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
List<String> getAppsSortedByUpdateCheckTime(
|
||||
{DateTime? ignoreAppsCheckedAfter}) {
|
||||
{DateTime? ignoreAppsCheckedAfter,
|
||||
bool onlyCheckInstalledOrTrackOnlyApps = false}) {
|
||||
List<String> appIds = apps.values
|
||||
.where((app) =>
|
||||
app.app.lastUpdateCheck == null ||
|
||||
ignoreAppsCheckedAfter == null ||
|
||||
app.app.lastUpdateCheck!.isBefore(ignoreAppsCheckedAfter))
|
||||
.where((app) {
|
||||
if (!onlyCheckInstalledOrTrackOnlyApps) {
|
||||
return true;
|
||||
} else {
|
||||
return app.app.installedVersion != null ||
|
||||
app.app.additionalSettings['trackOnly'] == true;
|
||||
}
|
||||
})
|
||||
.map((e) => e.app.id)
|
||||
.toList();
|
||||
appIds.sort((a, b) =>
|
||||
@ -1073,14 +1111,18 @@ class AppsProvider with ChangeNotifier {
|
||||
Future<List<App>> checkUpdates(
|
||||
{DateTime? ignoreAppsCheckedAfter,
|
||||
bool throwErrorsForRetry = false,
|
||||
List<String>? specificIds}) async {
|
||||
List<String>? specificIds,
|
||||
SettingsProvider? sp}) async {
|
||||
SettingsProvider settingsProvider = sp ?? this.settingsProvider;
|
||||
List<App> updates = [];
|
||||
MultiAppMultiError errors = MultiAppMultiError();
|
||||
if (!gettingUpdates) {
|
||||
gettingUpdates = true;
|
||||
try {
|
||||
List<String> appIds = getAppsSortedByUpdateCheckTime(
|
||||
ignoreAppsCheckedAfter: ignoreAppsCheckedAfter);
|
||||
ignoreAppsCheckedAfter: ignoreAppsCheckedAfter,
|
||||
onlyCheckInstalledOrTrackOnlyApps:
|
||||
settingsProvider.onlyCheckInstalledOrTrackOnlyApps);
|
||||
if (specificIds != null) {
|
||||
appIds = appIds.where((aId) => specificIds.contains(aId)).toList();
|
||||
}
|
||||
@ -1131,7 +1173,7 @@ class AppsProvider with ChangeNotifier {
|
||||
return updateAppIds;
|
||||
}
|
||||
|
||||
Future<String?> exportApps(
|
||||
Future<String?> export(
|
||||
{bool pickOnly = false, isAuto = false, SettingsProvider? sp}) async {
|
||||
SettingsProvider settingsProvider = sp ?? this.settingsProvider;
|
||||
var exportDir = await settingsProvider.getExportDir();
|
||||
@ -1161,12 +1203,22 @@ class AppsProvider with ChangeNotifier {
|
||||
}
|
||||
String? returnPath;
|
||||
if (!pickOnly) {
|
||||
Map<String, dynamic> finalExport = {};
|
||||
finalExport['apps'] = apps.values.map((e) => e.app.toJson()).toList();
|
||||
if (settingsProvider.exportSettings) {
|
||||
finalExport['settings'] = Map<String, Object?>.fromEntries(
|
||||
(settingsProvider.prefs
|
||||
?.getKeys()
|
||||
.map((key) =>
|
||||
MapEntry(key, settingsProvider.prefs?.get(key)))
|
||||
.toList()) ??
|
||||
[]);
|
||||
}
|
||||
var result = await saf.createFile(exportDir,
|
||||
displayName:
|
||||
'${tr('obtainiumExportHyphenatedLowercase')}-${DateTime.now().toIso8601String().replaceAll(':', '-')}${isAuto ? '-auto' : ''}.json',
|
||||
mimeType: 'application/json',
|
||||
bytes: Uint8List.fromList(utf8.encode(
|
||||
jsonEncode(apps.values.map((e) => e.app.toJson()).toList()))));
|
||||
bytes: Uint8List.fromList(utf8.encode(jsonEncode(finalExport))));
|
||||
if (result == null) {
|
||||
throw ObtainiumError(tr('unexpectedError'));
|
||||
}
|
||||
@ -1176,10 +1228,13 @@ class AppsProvider with ChangeNotifier {
|
||||
return returnPath;
|
||||
}
|
||||
|
||||
Future<int> importApps(String appsJSON) async {
|
||||
List<App> importedApps = (jsonDecode(appsJSON) as List<dynamic>)
|
||||
.map((e) => App.fromJson(e))
|
||||
.toList();
|
||||
Future<MapEntry<int, bool>> import(String appsJSON) async {
|
||||
var decodedJSON = jsonDecode(appsJSON);
|
||||
var newFormat = !(decodedJSON is List);
|
||||
List<App> importedApps =
|
||||
((newFormat ? decodedJSON['apps'] : decodedJSON) as List<dynamic>)
|
||||
.map((e) => App.fromJson(e))
|
||||
.toList();
|
||||
while (loadingApps) {
|
||||
await Future.delayed(const Duration(microseconds: 1));
|
||||
}
|
||||
@ -1190,7 +1245,20 @@ class AppsProvider with ChangeNotifier {
|
||||
}
|
||||
await saveApps(importedApps, onlyIfExists: false);
|
||||
notifyListeners();
|
||||
return importedApps.length;
|
||||
if (newFormat && decodedJSON['settings'] != null) {
|
||||
var settingsMap = decodedJSON['settings'] as Map<String, Object?>;
|
||||
settingsMap.forEach((key, value) {
|
||||
if (value is int) {
|
||||
settingsProvider.prefs?.setInt(key, value);
|
||||
} else if (value is bool) {
|
||||
settingsProvider.prefs?.setBool(key, value);
|
||||
} else {
|
||||
settingsProvider.prefs?.setString(key, value as String);
|
||||
}
|
||||
});
|
||||
}
|
||||
return MapEntry<int, bool>(
|
||||
importedApps.length, newFormat && decodedJSON['settings'] != null);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1199,9 +1267,11 @@ class AppsProvider with ChangeNotifier {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<List<List<String>>> addAppsByURL(List<String> urls) async {
|
||||
Future<List<List<String>>> addAppsByURL(List<String> urls,
|
||||
{AppSource? sourceOverride}) async {
|
||||
List<dynamic> results = await SourceProvider().getAppsByURLNaive(urls,
|
||||
alreadyAddedUrls: apps.values.map((e) => e.app.url).toList());
|
||||
alreadyAddedUrls: apps.values.map((e) => e.app.url).toList(),
|
||||
sourceOverride: sourceOverride);
|
||||
List<App> pps = results[0];
|
||||
Map<String, dynamic> errorsMap = results[1];
|
||||
for (var app in pps) {
|
||||
@ -1362,7 +1432,9 @@ Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
|
||||
entry['key'] as String, entry['value'] as int))
|
||||
.toList() ??
|
||||
appsProvider
|
||||
.getAppsSortedByUpdateCheckTime()
|
||||
.getAppsSortedByUpdateCheckTime(
|
||||
onlyCheckInstalledOrTrackOnlyApps: appsProvider
|
||||
.settingsProvider.onlyCheckInstalledOrTrackOnlyApps)
|
||||
.map((e) => MapEntry(e, 0)))
|
||||
];
|
||||
List<MapEntry<String, int>> toInstall = <MapEntry<String, int>>[
|
||||
@ -1446,7 +1518,8 @@ Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
|
||||
// Check for updates
|
||||
notificationsProvider.notify(notif, cancelExisting: true);
|
||||
updates = await appsProvider.checkUpdates(
|
||||
specificIds: toCheck.map((e) => e.key).toList());
|
||||
specificIds: toCheck.map((e) => e.key).toList(),
|
||||
sp: appsProvider.settingsProvider);
|
||||
} catch (e) {
|
||||
// If there were errors, group them into toRetry and toThrow based on max retry count per app
|
||||
if (e is Map) {
|
||||
|
@ -213,7 +213,8 @@ class SettingsProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
String? getSettingString(String settingId) {
|
||||
return prefs?.getString(settingId);
|
||||
String? str = prefs?.getString(settingId);
|
||||
return str?.isNotEmpty == true ? str : null;
|
||||
}
|
||||
|
||||
void setSettingString(String settingId, String value) {
|
||||
@ -406,4 +407,22 @@ class SettingsProvider with ChangeNotifier {
|
||||
prefs?.setBool('autoExportOnChanges', val);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool get onlyCheckInstalledOrTrackOnlyApps {
|
||||
return prefs?.getBool('onlyCheckInstalledOrTrackOnlyApps') ?? false;
|
||||
}
|
||||
|
||||
set onlyCheckInstalledOrTrackOnlyApps(bool val) {
|
||||
prefs?.setBool('onlyCheckInstalledOrTrackOnlyApps', val);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool get exportSettings {
|
||||
return prefs?.getBool('exportSettings') ?? false;
|
||||
}
|
||||
|
||||
set exportSettings(bool val) {
|
||||
prefs?.setBool('exportSettings', val);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
@ -67,10 +67,11 @@ appJSONCompatibilityModifiers(Map<String, dynamic> json) {
|
||||
.reduce((value, element) => [...value, ...element]);
|
||||
Map<String, dynamic> additionalSettings =
|
||||
getDefaultValuesFromFormItems([formItems]);
|
||||
Map<String, dynamic> originalAdditionalSettings = {};
|
||||
if (json['additionalSettings'] != null) {
|
||||
additionalSettings.addEntries(
|
||||
Map<String, dynamic>.from(jsonDecode(json['additionalSettings']))
|
||||
.entries);
|
||||
originalAdditionalSettings =
|
||||
Map<String, dynamic>.from(jsonDecode(json['additionalSettings']));
|
||||
additionalSettings.addEntries(originalAdditionalSettings.entries);
|
||||
}
|
||||
// If needed, migrate old-style additionalData to newer-style additionalSettings (V1)
|
||||
if (json['additionalData'] != null) {
|
||||
@ -134,6 +135,11 @@ appJSONCompatibilityModifiers(Map<String, dynamic> json) {
|
||||
if (additionalSettings['autoApkFilterByArch'] == null) {
|
||||
additionalSettings['autoApkFilterByArch'] = false;
|
||||
}
|
||||
// HTML 'fixed URL' support should be disabled if it previously did not exist
|
||||
if (source.runtimeType == HTML().runtimeType &&
|
||||
originalAdditionalSettings['supportFixedAPKURL'] == null) {
|
||||
additionalSettings['supportFixedAPKURL'] = false;
|
||||
}
|
||||
json['additionalSettings'] = jsonEncode(additionalSettings);
|
||||
// F-Droid no longer needs cloudflare exception since override can be used - migrate apps appropriately
|
||||
// This allows us to reverse the changes made for issue #418 (support cloudflare.f-droid)
|
||||
@ -283,9 +289,6 @@ preStandardizeUrl(String url) {
|
||||
url.toLowerCase().indexOf('https://') != 0) {
|
||||
url = 'https://$url';
|
||||
}
|
||||
if (url.toLowerCase().indexOf('https://www.') == 0) {
|
||||
url = 'https://${url.substring(12)}';
|
||||
}
|
||||
url = url
|
||||
.split('/')
|
||||
.where((e) => e.isNotEmpty)
|
||||
@ -451,7 +454,8 @@ abstract class AppSource {
|
||||
[
|
||||
GeneratedFormSwitch('skipUpdateNotifications',
|
||||
label: tr('skipUpdateNotifications'))
|
||||
]
|
||||
],
|
||||
[GeneratedFormTextField('about', label: tr('about'), required: false)]
|
||||
];
|
||||
|
||||
// Previous 2 variables combined into one at runtime for convenient usage
|
||||
@ -599,7 +603,7 @@ class SourceProvider {
|
||||
AppSource? source;
|
||||
for (var s in sources.where((element) => element.host != null)) {
|
||||
if (RegExp(
|
||||
'://${s.allowSubDomains ? '([^\\.]+\\.)*' : ''}${s.host}(/|\\z)?')
|
||||
'://${s.allowSubDomains ? '([^\\.]+\\.)*' : '(www\\.)?'}${s.host}(/|\\z)?')
|
||||
.hasMatch(url)) {
|
||||
source = s;
|
||||
break;
|
||||
@ -676,7 +680,6 @@ class SourceProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
String apkVersion = apk.version.replaceAll('/', '-');
|
||||
var name = currentApp != null ? currentApp.name.trim() : '';
|
||||
name = name.isNotEmpty ? name : apk.names.name;
|
||||
App finalApp = App(
|
||||
@ -691,7 +694,7 @@ class SourceProvider {
|
||||
apk.names.author,
|
||||
name,
|
||||
currentApp?.installedVersion,
|
||||
apkVersion,
|
||||
apk.version,
|
||||
apk.apkUrls,
|
||||
apk.apkUrls.length - 1 >= 0 ? apk.apkUrls.length - 1 : 0,
|
||||
additionalSettings,
|
||||
@ -710,7 +713,8 @@ class SourceProvider {
|
||||
|
||||
// Returns errors in [results, errors] instead of throwing them
|
||||
Future<List<dynamic>> getAppsByURLNaive(List<String> urls,
|
||||
{List<String> alreadyAddedUrls = const []}) async {
|
||||
{List<String> alreadyAddedUrls = const [],
|
||||
AppSource? sourceOverride}) async {
|
||||
List<App> apps = [];
|
||||
Map<String, dynamic> errors = {};
|
||||
for (var url in urls) {
|
||||
@ -718,7 +722,7 @@ class SourceProvider {
|
||||
if (alreadyAddedUrls.contains(url)) {
|
||||
throw ObtainiumError(tr('appAlreadyAdded'));
|
||||
}
|
||||
var source = getSource(url);
|
||||
var source = sourceOverride ?? getSource(url);
|
||||
apps.add(await getApp(
|
||||
source,
|
||||
url,
|
||||
|
242
pubspec.lock
242
pubspec.lock
@ -5,10 +5,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: android_alarm_manager_plus
|
||||
sha256: "82fb28c867c4b3dd7e9157728e46426b8916362f977dbba46b949210f00099f4"
|
||||
sha256: "84720c8ad2758aabfbeafd24a8c355d8c8dd3aa52b01eaf3bb827c7210f61a91"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.4"
|
||||
android_intent_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -38,18 +38,26 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: animations
|
||||
sha256: ef57563eed3620bd5d75ad96189846aca1e033c0c45fc9a7d26e80ab02b88a70
|
||||
sha256: "708e4b68c23228c264b038fe7003a2f5d01ce85fc64d8cae090e86b27fcea6c5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
version: "2.0.10"
|
||||
app_links:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: app_links
|
||||
sha256: "4e392b5eba997df356ca6021f28431ce1cfeb16758699553a94b13add874a3bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.5.0"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "7e0d52067d05f2e0324268097ba723b71cb41ac8a6a2b24d1edf9c536b987b03"
|
||||
sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.6"
|
||||
version: "3.4.9"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -94,10 +102,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
|
||||
sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
version: "0.4.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -110,18 +118,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.2"
|
||||
version: "1.18.0"
|
||||
connectivity_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: connectivity_plus
|
||||
sha256: "94d51c6f1299133a2baa4c5c3d2c11ec7d7fb4768dee5c52a56f7d7522fcf70e"
|
||||
sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
version: "5.0.2"
|
||||
connectivity_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -142,12 +150,12 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: "445db18de832dba8d851e287aff8ccf169bed30d2e94243cb54c7d2f1ed2142c"
|
||||
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+6"
|
||||
version: "0.3.3+8"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
@ -174,18 +182,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dbus
|
||||
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
|
||||
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.8"
|
||||
version: "0.7.10"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659"
|
||||
sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.0.3"
|
||||
version: "9.1.1"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -198,10 +206,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dynamic_color
|
||||
sha256: "96bff3df72e3d428bda2b874c7a521e8c86f592cae626ea594922fcc8d166e0c"
|
||||
sha256: "8b8bd1d798bd393e11eddeaa8ae95b12ff028bf7d5998fc5d003488cd5f4ce2f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.6.7"
|
||||
version: "1.6.8"
|
||||
easy_localization:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -246,10 +254,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
sha256: "903dd4ba13eae7cef64acc480e91bf54c3ddd23b5b90b639c170f3911e489620"
|
||||
sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
version: "6.1.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -283,18 +291,18 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
||||
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
version: "3.0.1"
|
||||
flutter_local_notifications:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: "6d11ea777496061e583623aaf31923f93a9409ef8fcaeeefdd6cd78bf4fe5bb3"
|
||||
sha256: bb5cd63ff7c91d6efe452e41d0d0ae6348925c82eafd10ce170ef585ea04776e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "16.1.0"
|
||||
version: "16.2.0"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -320,18 +328,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_markdown
|
||||
sha256: "8afc9a6aa6d8e8063523192ba837149dbf3d377a37c0b0fc579149a1fbd4a619"
|
||||
sha256: "35108526a233cc0755664d445f8a6b4b61e6f8fe993b3658b80b4a26827fc196"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.18"
|
||||
version: "0.6.18+2"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c
|
||||
sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.16"
|
||||
version: "2.0.17"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -346,10 +354,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fluttertoast
|
||||
sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c"
|
||||
sha256: dfdde255317af381bfc1c486ed968d5a43a2ded9c931e87cbecd88767d6a71c1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.2.2"
|
||||
version: "8.2.4"
|
||||
gtk:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: gtk
|
||||
sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
hsluv:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -370,10 +386,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
|
||||
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.2"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -418,10 +434,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "3.0.0"
|
||||
markdown:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -450,10 +466,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -498,10 +514,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1"
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "2.2.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -538,50 +554,58 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
|
||||
sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.0.1"
|
||||
version: "11.1.0"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e
|
||||
sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.1.0"
|
||||
version: "12.0.1"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
|
||||
sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.4"
|
||||
version: "9.2.0"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "11b762a8c123dced6461933a88ea1edbbe036078c3f9f41b08886e678e7864df"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.0+2"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
|
||||
sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.12.0"
|
||||
version: "4.0.2"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
|
||||
sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
version: "0.2.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.0"
|
||||
version: "6.0.2"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -594,10 +618,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
|
||||
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.6"
|
||||
version: "2.1.7"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -610,26 +634,26 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
|
||||
sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.5"
|
||||
version: "6.1.1"
|
||||
share_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: share_plus
|
||||
sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11"
|
||||
sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.1.0"
|
||||
version: "7.2.1"
|
||||
share_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus_platform_interface
|
||||
sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7"
|
||||
sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
version: "3.3.1"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -674,10 +698,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
|
||||
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
version: "2.2.2"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -707,6 +731,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
sqflite:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -719,26 +751,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a"
|
||||
sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
version: "2.5.0+2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -767,10 +799,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
version: "0.6.1"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -791,74 +823,74 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27"
|
||||
sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.14"
|
||||
version: "6.2.2"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330
|
||||
sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
version: "6.2.0"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f"
|
||||
sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.5"
|
||||
version: "6.2.1"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e
|
||||
sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
version: "3.1.1"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88
|
||||
sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.7"
|
||||
version: "3.1.0"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618"
|
||||
sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
version: "2.2.0"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5"
|
||||
sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.20"
|
||||
version: "2.2.2"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069"
|
||||
sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.8"
|
||||
version: "3.1.1"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
|
||||
sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.7"
|
||||
version: "4.2.2"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -871,50 +903,50 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
version: "0.3.0"
|
||||
webview_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: webview_flutter
|
||||
sha256: c1ab9b81090705c6069197d9fdc1625e587b52b8d70cdde2339d177ad0dbb98e
|
||||
sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.4.1"
|
||||
version: "4.4.2"
|
||||
webview_flutter_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_android
|
||||
sha256: b0cd33dd7d3dd8e5f664e11a19e17ba12c352647269921a3b568406b001f1dff
|
||||
sha256: e313dcdf45d4c95bcb8960351ef2389b7f0687b90bc92483f7f7983ae5758456
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.12.0"
|
||||
version: "3.13.0"
|
||||
webview_flutter_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_platform_interface
|
||||
sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f"
|
||||
sha256: "68e86162aa8fc646ae859e1585995c096c95fc2476881fa0c4a8d10f56013a5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
version: "2.8.0"
|
||||
webview_flutter_wkwebview:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: "30b9af6bdd457b44c08748b9190d23208b5165357cc2eb57914fee1366c42974"
|
||||
sha256: accdaaa49a2aca2dc3c3230907988954cdd23fed0a19525d6c9789d380f4dc76
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.9.1"
|
||||
version: "3.9.4"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
|
||||
sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.9"
|
||||
version: "5.1.1"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -935,10 +967,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
version: "6.5.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -948,5 +980,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.1.0 <4.0.0"
|
||||
flutter: ">=3.13.0"
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
flutter: ">=3.16.0"
|
||||
|
@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 0.14.30+222 # When changing this, update the tag in main() accordingly
|
||||
version: 0.14.37+231 # When changing this, update the tag in main() accordingly
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
@ -66,6 +66,8 @@ dependencies:
|
||||
hsluv: ^1.1.3
|
||||
connectivity_plus: ^5.0.0
|
||||
shared_storage: ^0.8.0
|
||||
crypto: ^3.0.3
|
||||
app_links: ^3.5.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@ -77,7 +79,7 @@ dev_dependencies:
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^2.0.1
|
||||
flutter_lints: ^3.0.0
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: "ic_launcher"
|
||||
|
Reference in New Issue
Block a user