Compare commits
181 Commits
v0.15.6-be
...
v1.0.3
Author | SHA1 | Date | |
---|---|---|---|
a5b3b9d1d0 | |||
13cd7e76c1 | |||
6e7ccfba37 | |||
34fd673e25 | |||
db484f7b28 | |||
b4cf0f5d29 | |||
4db205dd9a | |||
64f8e2a57b | |||
eddc245ff4 | |||
ed2f0f2c0c | |||
7d5a422855 | |||
e420862546 | |||
2cc59948a7 | |||
188d33199e | |||
24928261bb | |||
4c7bda8343 | |||
d88709c999 | |||
29e1481a3b | |||
9d76359543 | |||
f50e791221 | |||
7d08e5225c | |||
3842c1e2df | |||
21b1990991 | |||
e278c9fb5a | |||
bfa29bb7c2 | |||
efa55a9696 | |||
8888cd6264 | |||
34e2c014e3 | |||
5d92a6d013 | |||
fb03b2e95c | |||
5a1e09564c | |||
3783eba401 | |||
a3530ce6bb | |||
27d8655d58 | |||
fb845ce601 | |||
dbd433df9d | |||
badf32ff11 | |||
5e40f3264e | |||
71bb6d9410 | |||
731b682fc9 | |||
c9751227a5 | |||
6ef2a26e94 | |||
5a8efa2388 | |||
d25895fa28 | |||
de09f3ece2 | |||
1135ffb30f | |||
5379cb31e8 | |||
7d41ab44b7 | |||
b239f9bd05 | |||
1acc923ec2 | |||
8d6edfb91f | |||
491b62bb0d | |||
d1413fc478 | |||
761f7039e9 | |||
59783a341d | |||
0100fa4236 | |||
f6f9ed68dc | |||
8adb5e84d1 | |||
3940b65156 | |||
98e7f27eab | |||
7cf5cafd75 | |||
d750e35273 | |||
1f12e12130 | |||
4a4fb4716e | |||
efe6ec0d43 | |||
00d605e195 | |||
f06de8d19f | |||
fac335c849 | |||
5bef546ae4 | |||
b690cd6a67 | |||
dbee4a2657 | |||
67420f293b | |||
d1d6b0792b | |||
2ec039ba0f | |||
4b9b9a10ad | |||
4193d8ada1 | |||
4701b090b0 | |||
8b0c85827c | |||
57e02d1c80 | |||
4446929b10 | |||
c31f65b0e4 | |||
f6c3b8dceb | |||
10bd825972 | |||
303bee7c57 | |||
369ae43062 | |||
62dc7fd88b | |||
4aace63cd7 | |||
5d588a05a7 | |||
cab6f9d026 | |||
fc94d553eb | |||
2952345585 | |||
becc3828b7 | |||
2a62248991 | |||
eb2b31219c | |||
55053f9627 | |||
5ff6c64938 | |||
c1c517cf38 | |||
b3de2e5d6b | |||
0183070b2b | |||
089bbc3ee9 | |||
b085801c2c | |||
ad4cae4288 | |||
95c285e1f7 | |||
c31a1912a5 | |||
99da1f8481 | |||
bf6b3a7da0 | |||
4ab4f58f65 | |||
29a76ac8e6 | |||
e2761ce284 | |||
dc45334cb9 | |||
56052bfd79 | |||
f5067d636a | |||
b173b1300a | |||
15a34e53bf | |||
183fb26988 | |||
2da9a8cd59 | |||
bb07000280 | |||
3a46ad2957 | |||
6b631d119c | |||
051762fcc1 | |||
595d5dc283 | |||
1d328f07e2 | |||
b1c8ac6f2a | |||
da619d37f7 | |||
236c4722e5 | |||
92f59116a0 | |||
c28040f0cb | |||
e8b9654320 | |||
be1a793a37 | |||
440720afb6 | |||
900d3e734e | |||
0bf096abb5 | |||
632efb9e22 | |||
bfc506e450 | |||
ffe612708c | |||
5d161160aa | |||
eadf3e5a29 | |||
6b6b4084a0 | |||
30a4633f72 | |||
d44139dd72 | |||
60869a0490 | |||
102be5fa2e | |||
a25c04b390 | |||
d46f0a1c33 | |||
5c7f5a99e1 | |||
d949a80f19 | |||
6b5d4e2027 | |||
199d071ee8 | |||
5b78de5d61 | |||
db4f13e2e1 | |||
5e869b7e03 | |||
34fee36132 | |||
ea09bc36a5 | |||
f7e0678cb2 | |||
223ae378a9 | |||
6f52a48991 | |||
0280935955 | |||
eebc7d9ab3 | |||
aa7b5652ff | |||
ec6683a198 | |||
05372924a0 | |||
e63c1399dd | |||
4fcad92e1d | |||
e18e7298bc | |||
76a6a509cd | |||
7a03561ff6 | |||
70e54ce14a | |||
b5f86f0e79 | |||
4ebca49ef7 | |||
49cfa95463 | |||
4600ab0593 | |||
7f2ca98bde | |||
6511485bcf | |||
fd22113e44 | |||
f2ae078723 | |||
c3dacf2b9b | |||
e8580dc1d5 | |||
daffff7eb0 | |||
751fda5e37 | |||
1e38abc500 | |||
7987083555 |
1
.flutter
Submodule
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -10,6 +10,7 @@ assignees: ''
|
|||||||
**Prerequisites**
|
**Prerequisites**
|
||||||
<!-- Please ensure your request is not part of an existing issue. -->
|
<!-- Please ensure your request is not part of an existing issue. -->
|
||||||
<!-- Please ensure you have checked the Obtainium Wiki. -->
|
<!-- Please ensure you have checked the Obtainium Wiki. -->
|
||||||
|
<!-- Please ensure your request is an actual bug and not intended behaviour (this is frequently the case for issues involving version strings and the HTML source. -->
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
<!-- A clear and concise description of what the bug is. -->
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -14,11 +14,14 @@ assignees: ''
|
|||||||
**Describe the feature**
|
**Describe the feature**
|
||||||
<!-- A clear and concise description of what you want to happen.
|
<!-- A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
For new Sources, it's preferable (not required) if you suggest how the following details can be extracted from the Source in a reliable way (like an API or through web scraping):
|
For new Sources, please ensure:
|
||||||
|
1. It is not already possible to use the HTML Source for your purposes.
|
||||||
|
2. It must be possible to extract the following details from the Source in a reliable way:
|
||||||
- The App version (or any release-specific identifier - a "pseudo-version") for the latest release
|
- The App version (or any release-specific identifier - a "pseudo-version") for the latest release
|
||||||
- One or more APK URL(s) for the latest release
|
- One or more APK URL(s) for the latest release
|
||||||
- Above details for previous releases (optional)
|
- Above details for previous releases (optional)
|
||||||
|
|
||||||
|
If you're not sure about 1 or 2, open a discussion item instead.
|
||||||
Note that the Web scraper cannot deal with JavaScript-enabled content. -->
|
Note that the Web scraper cannot deal with JavaScript-enabled content. -->
|
||||||
|
|
||||||
**Describe alternatives you've considered (if applicable)**
|
**Describe alternatives you've considered (if applicable)**
|
||||||
|
39
.github/workflows/release.yml
vendored
@ -2,6 +2,10 @@ name: Build and Release
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
beta:
|
||||||
|
type: boolean
|
||||||
|
description: Is beta?
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -19,11 +23,34 @@ jobs:
|
|||||||
gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }}
|
gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }}
|
||||||
passphrase: ${{ secrets.PGP_PASSPHRASE }}
|
passphrase: ${{ secrets.PGP_PASSPHRASE }}
|
||||||
|
|
||||||
|
- name: Check submodule
|
||||||
|
id: check_submodule
|
||||||
|
run: |
|
||||||
|
SUBMODULE_COMMIT_LONG="$(git submodule status | head -1 | tail -c +2 | awk '{print $1}')"
|
||||||
|
FLUTTER_COMMIT_SHORT="$(flutter --version | head -2 | tail -1 | awk '{print $4}')"
|
||||||
|
echo "SUBMODULE_COMMIT_LONG=$SUBMODULE_COMMIT_LONG, FLUTTER_COMMIT_SHORT=$FLUTTER_COMMIT_SHORT"
|
||||||
|
if ! [[ "$SUBMODULE_COMMIT_LONG" =~ ^$FLUTTER_COMMIT_SHORT ]]; then
|
||||||
|
echo "Your submodule has not been updated!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Extract Version
|
||||||
|
id: extract_version
|
||||||
|
run: |
|
||||||
|
VERSION=$(grep -oP "^version: [^\+]+" pubspec.yaml | tail -c +10)
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
if [ ${{ inputs.beta }} == true ]; then BETA=true; else BETA=false; fi
|
||||||
|
echo "beta=$BETA" >> $GITHUB_OUTPUT
|
||||||
|
TAG="v$VERSION"
|
||||||
|
if [ $BETA == true ]; then TAG="$TAG"-beta; fi
|
||||||
|
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build APKs
|
- name: Build APKs
|
||||||
run: |
|
run: |
|
||||||
sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle
|
sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle
|
||||||
flutter build apk --flavor normal && flutter build apk --split-per-abi --flavor normal
|
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
|
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 && flutter build apk --split-per-abi --flavor fdroid -t lib/main_fdroid.dart
|
||||||
rm ./build/app/outputs/flutter-apk/*.sha1
|
rm ./build/app/outputs/flutter-apk/*.sha1
|
||||||
ls -l ./build/app/outputs/flutter-apk/
|
ls -l ./build/app/outputs/flutter-apk/
|
||||||
|
|
||||||
@ -37,22 +64,12 @@ jobs:
|
|||||||
for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do
|
for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do
|
||||||
unsignedFn=${apk/-release/-unsigned}
|
unsignedFn=${apk/-release/-unsigned}
|
||||||
mv "$apk" "$unsignedFn"
|
mv "$apk" "$unsignedFn"
|
||||||
${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}"
|
${ANDROID_HOME}/build-tools/$(ls ${ANDROID_HOME}/build-tools/ | tail -1)/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}"
|
||||||
sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256
|
sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256
|
||||||
gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256
|
gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256
|
||||||
done
|
done
|
||||||
rm apksign.keystore
|
rm apksign.keystore
|
||||||
PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}"
|
PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}"
|
||||||
|
|
||||||
- name: Extract Version
|
|
||||||
id: extract_version
|
|
||||||
run: |
|
|
||||||
VERSION=$(grep -oP "currentVersion = '\K[^']+" lib/main.dart)
|
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
TAG=$(grep -oP "'.*\\\$currentVersion.*'" lib/main.dart | head -c -2 | tail -c +2 | sed "s/\$currentVersion/$VERSION/g")
|
|
||||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
|
||||||
if [ -n "$(echo $TAG | grep -oP '\-beta$')" ]; then BETA=true; else BETA=false; fi
|
|
||||||
echo "beta=$BETA" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Create Tag
|
- name: Create Tag
|
||||||
uses: mathieudutour/github-tag-action@v6.1
|
uses: mathieudutour/github-tag-action@v6.1
|
||||||
|
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule ".flutter"]
|
||||||
|
path = .flutter
|
||||||
|
url = https://github.com/flutter/flutter/
|
@ -21,7 +21,7 @@ Currently supported App sources:
|
|||||||
- [SourceForge](https://sourceforge.net/)
|
- [SourceForge](https://sourceforge.net/)
|
||||||
- [SourceHut](https://git.sr.ht/)
|
- [SourceHut](https://git.sr.ht/)
|
||||||
- Other - General:
|
- Other - General:
|
||||||
- [APKPure](https://apkpure.com/)
|
- [APKPure](https://apkpure.net/)
|
||||||
- [Aptoide](https://aptoide.com/)
|
- [Aptoide](https://aptoide.com/)
|
||||||
- [Uptodown](https://uptodown.com/)
|
- [Uptodown](https://uptodown.com/)
|
||||||
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
||||||
@ -42,6 +42,9 @@ Currently supported App sources:
|
|||||||
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
|
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
|
||||||
alt="Get it on GitHub"
|
alt="Get it on GitHub"
|
||||||
height="80">](https://github.com/ImranR98/Obtainium/releases)
|
height="80">](https://github.com/ImranR98/Obtainium/releases)
|
||||||
|
[<img src="https://gitlab.com/fdroid/artwork/-/raw/master/badge/get-it-on.png"
|
||||||
|
alt="Get it on F-Droid"
|
||||||
|
height="80">](https://f-droid.org/packages/dev.imranr.obtainium.fdroid/)
|
||||||
|
|
||||||
[PGP Public Key](https://keyserver.ubuntu.com/pks/lookup?search=contact%40imranr.dev&fingerprint=on&op=index)
|
[PGP Public Key](https://keyserver.ubuntu.com/pks/lookup?search=contact%40imranr.dev&fingerprint=on&op=index)
|
||||||
|
|
||||||
|
@ -108,3 +108,16 @@ dependencies {
|
|||||||
|
|
||||||
implementation "com.github.topjohnwu.libsu:core:5.2.2"
|
implementation "com.github.topjohnwu.libsu:core:5.2.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ext.abiCodes = ["x86_64": 1, "armeabi-v7a": 2, "arm64-v8a": 3]
|
||||||
|
import com.android.build.OutputFile
|
||||||
|
android.applicationVariants.all { variant ->
|
||||||
|
variant.outputs.each { output ->
|
||||||
|
def abiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
|
||||||
|
if (abiVersionCode != null) {
|
||||||
|
output.versionCodeOverride = variant.versionCode * 10 + abiVersionCode
|
||||||
|
} else {
|
||||||
|
output.versionCodeOverride = variant.versionCode * 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -64,13 +64,12 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
<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.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.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
|
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="29" />
|
android:maxSdkVersion="29" />\
|
||||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||||
</manifest>
|
</manifest>
|
BIN
assets/graphics/badge_obtainium.png
Normal file
After Width: | Height: | Size: 18 KiB |
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Napredak: {}%",
|
"percentProgress": "Napredak: {}%",
|
||||||
"pleaseWait": "Molimo sačekajte",
|
"pleaseWait": "Molimo sačekajte",
|
||||||
"updateAvailable": "Ažuriranje dostupno",
|
"updateAvailable": "Ažuriranje dostupno",
|
||||||
"estimateInBracketsShort": "(Procjena)",
|
|
||||||
"notInstalled": "Nije instalirano",
|
"notInstalled": "Nije instalirano",
|
||||||
"estimateInBrackets": "(Procjena)",
|
"pseudoVersion": "pseudo-verzija",
|
||||||
"selectAll": "Označi sve",
|
"selectAll": "Označi sve",
|
||||||
"deselectX": "Poništi odabir {}",
|
"deselectX": "Poništi odabir {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} će biti uklonjen iz Obtainiuma, ali će ostati instaliran na uređaju.",
|
"xWillBeRemovedButRemainInstalled": "{} će biti uklonjen iz Obtainiuma, ali će ostati instaliran na uređaju.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Otkvači sa vrha",
|
"unpinFromTop": "Otkvači sa vrha",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Resetujte status instalacije za odabrane aplikacije?",
|
"resetInstallStatusForSelectedAppsQuestion": "Resetujte status instalacije za odabrane aplikacije?",
|
||||||
"installStatusOfXWillBeResetExplanation": "Status instalacije bilo koje odabrane aplikacije će se resetovati.\n\nTo može pomoći kada je verzija aplikacije prikazana u Obtainiumu netačna zbog neuspjelih ažuriranja ili drugih problema.",
|
"installStatusOfXWillBeResetExplanation": "Status instalacije bilo koje odabrane aplikacije će se resetovati.\n\nTo može pomoći kada je verzija aplikacije prikazana u Obtainiumu netačna zbog neuspjelih ažuriranja ili drugih problema.",
|
||||||
|
"customLinkMessage": "Ove veze rade na uređajima s instaliranim Obtainiumom",
|
||||||
|
"shareAppConfigLinks": "Podijelite konfiguraciju aplikacije kao HTML vezu",
|
||||||
"shareSelectedAppURLs": "Podijeli odabrane URL-ove aplikacija",
|
"shareSelectedAppURLs": "Podijeli odabrane URL-ove aplikacija",
|
||||||
"resetInstallStatus": "Resetujte status instalacije",
|
"resetInstallStatus": "Resetujte status instalacije",
|
||||||
"more": "Više",
|
"more": "Više",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Tamna",
|
"dark": "Tamna",
|
||||||
"light": "Svijetla",
|
"light": "Svijetla",
|
||||||
"followSystem": "Pratite sistem",
|
"followSystem": "Pratite sistem",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Koristite čisto crnu tamnu temu",
|
"useBlackTheme": "Koristite čisto crnu tamnu temu",
|
||||||
"appSortBy": "Aplikacije sortirane po",
|
"appSortBy": "Aplikacije sortirane po",
|
||||||
"authorName": "Autor/Ime",
|
"authorName": "Autor/Ime",
|
||||||
@ -169,13 +168,12 @@
|
|||||||
"lastUpdateCheckX": "Posljednja provjera ažuriranja: {}",
|
"lastUpdateCheckX": "Posljednja provjera ažuriranja: {}",
|
||||||
"remove": "Izbriši",
|
"remove": "Izbriši",
|
||||||
"yesMarkUpdated": "Da, označi kao ažurirano",
|
"yesMarkUpdated": "Da, označi kao ažurirano",
|
||||||
"fdroid": "F-Droid Official",
|
"fdroid": "Službeni F-Droid",
|
||||||
"appIdOrName": "ID ili ime aplikacije",
|
"appIdOrName": "ID ili ime aplikacije",
|
||||||
"appId": "Apl ID",
|
"appId": "Apl ID",
|
||||||
"appWithIdOrNameNotFound": "Nije pronađena aplikacija s tim ID-om ili imenom",
|
"appWithIdOrNameNotFound": "Nije pronađena aplikacija s tim ID-om ili imenom",
|
||||||
"reposHaveMultipleApps": "Repo-i mogu sadržavati više aplikacija",
|
"reposHaveMultipleApps": "Repo-i mogu sadržavati više aplikacija",
|
||||||
"fdroidThirdPartyRepo": "F-Droid Repo treće strane",
|
"fdroidThirdPartyRepo": "F-Droid Repo treće strane",
|
||||||
"steam": "Steam",
|
|
||||||
"steamMobile": "Steam Mobile",
|
"steamMobile": "Steam Mobile",
|
||||||
"steamChat": "Razgovor na Steamu (chat)",
|
"steamChat": "Razgovor na Steamu (chat)",
|
||||||
"install": "Instaliraj",
|
"install": "Instaliraj",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Promjene",
|
"changes": "Promjene",
|
||||||
"releaseDate": "Datum izdavanja",
|
"releaseDate": "Datum izdavanja",
|
||||||
"importFromURLsInFile": "Uvoz iz URL-ova u datoteci (kao što je OPML)",
|
"importFromURLsInFile": "Uvoz iz URL-ova u datoteci (kao što je OPML)",
|
||||||
|
"versionDetectionExplanation": "Pomiri niz verzije sa verzijom otkrivenom iz OS-a",
|
||||||
"versionDetection": "Otkrivanje verzije",
|
"versionDetection": "Otkrivanje verzije",
|
||||||
"standardVersionDetection": "Detekcija standardne verzije",
|
"standardVersionDetection": "Detekcija standardne verzije",
|
||||||
"groupByCategory": "Grupiši po kategoriji",
|
"groupByCategory": "Grupiši po kategoriji",
|
||||||
@ -235,7 +234,7 @@
|
|||||||
"addInfoInSettings": "Dodajte ove informacije u Postavkama.",
|
"addInfoInSettings": "Dodajte ove informacije u Postavkama.",
|
||||||
"githubSourceNote": "GitHub ograničavanje se može izbjeći korišćenjem tokena za lični pristup.",
|
"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.",
|
"gitlabSourceNote": "GitLab APK preuzimanje možda neće raditi bez tokena za lični pristup.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Sortiraj samo po zadnjem segmentu veze",
|
||||||
"filterReleaseNotesByRegEx": "Filtirajte promjene u izdanju po regularnom izrazu",
|
"filterReleaseNotesByRegEx": "Filtirajte promjene u izdanju po regularnom izrazu",
|
||||||
"customLinkFilterRegex": "Prilagođeni APK link filtrira se po regularnom izrazu (Zadano '.apk$')",
|
"customLinkFilterRegex": "Prilagođeni APK link filtrira se po regularnom izrazu (Zadano '.apk$')",
|
||||||
"appsPossiblyUpdated": "Pokušano ažuriranje aplikacija",
|
"appsPossiblyUpdated": "Pokušano ažuriranje aplikacija",
|
||||||
@ -245,10 +244,10 @@
|
|||||||
"backgroundUpdateReqsExplanation": "Ažuriranja u pozadini možda neće raditi za sve aplikacije.",
|
"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.",
|
"backgroundUpdateLimitsExplanation": "Uspjeh ažuriranja u pozadini se može provjeriti tek kada otvorite Obtainium.",
|
||||||
"verifyLatestTag": "Provjerite 'posljednu' ('latest') oznaku",
|
"verifyLatestTag": "Provjerite 'posljednu' ('latest') oznaku",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Filter za 'srednju' vezu za posjetu",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Filtriraj linkove prema tekstu linka",
|
||||||
"intermediateLinkNotFound": "Intermediate link nije nađen",
|
"intermediateLinkNotFound": "Intermediate link nije nađen",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "srednja karika",
|
||||||
"exemptFromBackgroundUpdates": "Izuzmi iz ažuriranja u pozadini (ako su uključeni)",
|
"exemptFromBackgroundUpdates": "Izuzmi iz ažuriranja u pozadini (ako su uključeni)",
|
||||||
"bgUpdatesOnWiFiOnly": "Isključite ažuriranje u pozadini kada niste na WiFi-ju",
|
"bgUpdatesOnWiFiOnly": "Isključite ažuriranje u pozadini kada niste na WiFi-ju",
|
||||||
"autoSelectHighestVersionCode": "Automatski izaberite najveću (verziju) versionCode APK-a",
|
"autoSelectHighestVersionCode": "Automatski izaberite najveću (verziju) versionCode APK-a",
|
||||||
@ -257,13 +256,13 @@
|
|||||||
"highlightTouchTargets": "Istaknite manje vidljive touch mete",
|
"highlightTouchTargets": "Istaknite manje vidljive touch mete",
|
||||||
"pickExportDir": "Izaberite datoteku za izvoz",
|
"pickExportDir": "Izaberite datoteku za izvoz",
|
||||||
"autoExportOnChanges": "Automatski izvezite pri promjenama",
|
"autoExportOnChanges": "Automatski izvezite pri promjenama",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Uključi postavke",
|
||||||
"filterVersionsByRegEx": "Filtrirajte verzije po regulatnom izrazu",
|
"filterVersionsByRegEx": "Filtrirajte verzije po regulatnom izrazu",
|
||||||
"trySelectingSuggestedVersionCode": "Probajte izabrati preloženu (verziju) versionCode APK-a",
|
"trySelectingSuggestedVersionCode": "Probajte izabrati preloženu (verziju) versionCode APK-a",
|
||||||
"dontSortReleasesList": "Zadrži redosled izdanja iz API-a",
|
"dontSortReleasesList": "Zadrži redosled izdanja iz API-a",
|
||||||
"reverseSort": "Obrni redosled",
|
"reverseSort": "Obrni redosled",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Uzmi prvi link",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Preskoči sortiranje",
|
||||||
"debugMenu": "Meni za otkrivanje grešaka",
|
"debugMenu": "Meni za otkrivanje grešaka",
|
||||||
"bgTaskStarted": "Rad u pozadini pokrenut - provjerite log-ove.",
|
"bgTaskStarted": "Rad u pozadini pokrenut - provjerite log-ove.",
|
||||||
"runBgCheckNow": "Pokrenite pozadinsku provjeru ažuriranja sad",
|
"runBgCheckNow": "Pokrenite pozadinsku provjeru ažuriranja sad",
|
||||||
@ -281,12 +280,27 @@
|
|||||||
"onlyCheckInstalledOrTrackOnlyApps": "Isključivo provjerite ažuriranje za instalirane i aplikacije 'samo za praćenje'",
|
"onlyCheckInstalledOrTrackOnlyApps": "Isključivo provjerite ažuriranje za instalirane i aplikacije 'samo za praćenje'",
|
||||||
"supportFixedAPKURL": "Podržite fiksne APK URL-ove",
|
"supportFixedAPKURL": "Podržite fiksne APK URL-ove",
|
||||||
"selectX": "Izaberite {}",
|
"selectX": "Izaberite {}",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "Dozvoli paralelna preuzimanja",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "Način instalacije",
|
||||||
"normal": "Normal",
|
"normal": "normalno",
|
||||||
"shizuku": "Shizuku",
|
"root": "korijen",
|
||||||
"root": "Root",
|
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"shizukuBinderNotFound": "Shizuku is not running",
|
||||||
|
"useSystemFont": "Koristite sistemski font",
|
||||||
|
"systemFontError": "Greška pri učitavanju sistemskog fonta: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Koristite kod verzije aplikacije kao verziju koju je otkrio OS",
|
||||||
|
"requestHeader": "Zaglavlje zahtjeva",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Koristite najnovije otpremanje materijala kao datum izdavanja",
|
||||||
|
"defaultPseudoVersioningMethod": "Zadana metoda pseudo-verzija",
|
||||||
|
"partialAPKHash": "Djelomični APK Hash",
|
||||||
|
"APKLinkHash": "APK Link Hash",
|
||||||
|
"directAPKLink": "Direktna APK veza",
|
||||||
|
"pseudoVersionInUse": "Pseudo-verzija je u upotrebi",
|
||||||
|
"installed": "Instalirano",
|
||||||
|
"latest": "Najnoviji",
|
||||||
|
"invertRegEx": "Obrni regularni izraz",
|
||||||
|
"note": "Note",
|
||||||
|
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
|
||||||
|
"badDownload": "The APK could not be parsed (incompatible or partial download)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Želite li ukloniti aplikaciju?",
|
"one": "Želite li ukloniti aplikaciju?",
|
||||||
"other": "Želite li ukloniti aplikacije?"
|
"other": "Želite li ukloniti aplikacije?"
|
||||||
|
@ -19,15 +19,15 @@
|
|||||||
"noDescription": "Žádný popis",
|
"noDescription": "Žádný popis",
|
||||||
"cancel": "Zrušit",
|
"cancel": "Zrušit",
|
||||||
"continue": "Pokračovat",
|
"continue": "Pokračovat",
|
||||||
"requiredInBracets": "(Required)",
|
"requiredInBrackets": "(Požadované)",
|
||||||
"dropdownNoOptsError": "ERROR: DROPDOWN MUSÍ MÍT AŽ JEDNU MOŽNOST",
|
"dropdownNoOptsError": "ERROR: DROPDOWN MUSÍ MÍT AŽ JEDNU MOŽNOST",
|
||||||
"colour": "Barva",
|
"colour": "Barva",
|
||||||
"githubStarredRepos": "GitHub Starred Repos",
|
"githubStarredRepos": "GitHub označená hvězdičkou",
|
||||||
"uname": "Uživatelské jméno",
|
"uname": "Uživatelské jméno",
|
||||||
"wrongArgNum": "Nesprávný počet zadaných argumentů",
|
"wrongArgNum": "Nesprávný počet zadaných argumentů",
|
||||||
"xIsTrackOnly":"{} je určeno pouze pro sledování",
|
"xIsTrackOnly": "{} je určeno pouze pro sledování",
|
||||||
"source": "Zdroj",
|
"source": "Zdroj",
|
||||||
"app": "App",
|
"app": "Aplikace",
|
||||||
"appsFromSourceAreTrackOnly": "Aplikace z tohoto zdroje jsou Jen sledovány.",
|
"appsFromSourceAreTrackOnly": "Aplikace z tohoto zdroje jsou Jen sledovány.",
|
||||||
"youPickedTrackOnly": "Vybrali jste možnost Jen sledovat.",
|
"youPickedTrackOnly": "Vybrali jste možnost Jen sledovat.",
|
||||||
"trackOnlyAppDescription": "Aplikace je sledována kvůli aktualizacím, ale Obtainium ji nebude stahovat ani instalovat.",
|
"trackOnlyAppDescription": "Aplikace je sledována kvůli aktualizacím, ale Obtainium ji nebude stahovat ani instalovat.",
|
||||||
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Pokrok: {}%",
|
"percentProgress": "Pokrok: {}%",
|
||||||
"pleaseWait": "Počkejte prosím",
|
"pleaseWait": "Počkejte prosím",
|
||||||
"updateAvailable": "Aktualizace je k dispozici",
|
"updateAvailable": "Aktualizace je k dispozici",
|
||||||
"estimateInBracketsShort": "(approx.)",
|
|
||||||
"notInstalled": "Není nainstalováno",
|
"notInstalled": "Není nainstalováno",
|
||||||
"estimateInBrackets": "(přibližně)",
|
"pseudoVersion": "pseudoverze",
|
||||||
"selectAll": "Vybrat vše",
|
"selectAll": "Vybrat vše",
|
||||||
"deselectX": "{} deselected",
|
"deselectX": "{} deselected",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} bude odstraněn z Obtainium, ale zůstane nainstalován v zařízení.",
|
"xWillBeRemovedButRemainInstalled": "{} bude odstraněn z Obtainium, ale zůstane nainstalován v zařízení.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Odepnout shora",
|
"unpinFromTop": "Odepnout shora",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Obnovit stav instalace vybraných aplikací?",
|
"resetInstallStatusForSelectedAppsQuestion": "Obnovit stav instalace vybraných aplikací?",
|
||||||
"installStatusOfXWillBeResetExplanation": "Stav instalace vybraných aplikací bude resetován. To může být užitečné, pokud je verze aplikace zobrazená v Obtainium nesprávná z důvodu neúspěšných aktualizací nebo jiných problémů.",
|
"installStatusOfXWillBeResetExplanation": "Stav instalace vybraných aplikací bude resetován. To může být užitečné, pokud je verze aplikace zobrazená v Obtainium nesprávná z důvodu neúspěšných aktualizací nebo jiných problémů.",
|
||||||
|
"customLinkMessage": "Tyto odkazy fungují na zařízeních s nainstalovaným Obtainium",
|
||||||
|
"shareAppConfigLinks": "Sdílet konfiguraci aplikace jako odkaz HTML",
|
||||||
"shareSelectedAppURLs": "Sdílet adresy URL vybraných aplikací",
|
"shareSelectedAppURLs": "Sdílet adresy URL vybraných aplikací",
|
||||||
"resetInstallStatus": "Obnovit stav instalace",
|
"resetInstallStatus": "Obnovit stav instalace",
|
||||||
"more": "Více",
|
"more": "Více",
|
||||||
@ -85,18 +86,18 @@
|
|||||||
"author": "Autor",
|
"author": "Autor",
|
||||||
"upToDateApps": "Aktuální apky",
|
"upToDateApps": "Aktuální apky",
|
||||||
"nonInstalledApps": "Neinstalované apky",
|
"nonInstalledApps": "Neinstalované apky",
|
||||||
"importExport": "Import/Export",
|
"importExport": "Import Export",
|
||||||
"settings": "Nastavení",
|
"settings": "Nastavení",
|
||||||
"exportedTo": "Exportováno do {}",
|
"exportedTo": "Exportováno do {}",
|
||||||
"obtainiumExport": "Obtainium Export",
|
"obtainiumExport": "Export obtainia",
|
||||||
"invalidInput": "Neplatný vstup",
|
"invalidInput": "Neplatný vstup",
|
||||||
"importedX": "Importováno {}",
|
"importedX": "Importováno {}",
|
||||||
"obtainiumImport": "Obtainium Import",
|
"obtainiumImport": "Dovoz obtainia",
|
||||||
"importFromURLList": "Import ze seznamu URL",
|
"importFromURLList": "Import ze seznamu URL",
|
||||||
"searchQuery": "Vyhledávací dotaz",
|
"searchQuery": "Vyhledávací dotaz",
|
||||||
"appURLList": "Seznam adres aplikací",
|
"appURLList": "Seznam adres aplikací",
|
||||||
"line": "Linka",
|
"line": "Linka",
|
||||||
"searchX": "Search {}",
|
"searchX": "Vyhledávání {}",
|
||||||
"noResults": "Nebyly nalezeny žádné výsledky",
|
"noResults": "Nebyly nalezeny žádné výsledky",
|
||||||
"importX": "Import {}",
|
"importX": "Import {}",
|
||||||
"importedAppsIdDisclaimer": "Importované aplikace mohou být nesprávně zobrazeny jako \"Neinstalovány\". Chcete-li to opravit, nainstalujte je znovu prostřednictvím Obtainium. To nemá vliv na data aplikací. Ovlivňuje pouze metody importu URL a třetích stran.",
|
"importedAppsIdDisclaimer": "Importované aplikace mohou být nesprávně zobrazeny jako \"Neinstalovány\". Chcete-li to opravit, nainstalujte je znovu prostřednictvím Obtainium. To nemá vliv na data aplikací. Ovlivňuje pouze metody importu URL a třetích stran.",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Tmavé",
|
"dark": "Tmavé",
|
||||||
"light": "Světlé",
|
"light": "Světlé",
|
||||||
"followSystem": "Jako systém",
|
"followSystem": "Jako systém",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Použít čistě černé tmavé téma",
|
"useBlackTheme": "Použít čistě černé tmavé téma",
|
||||||
"appSortBy": "Seřadit podle",
|
"appSortBy": "Seřadit podle",
|
||||||
"authorName": "Autor/Jméno",
|
"authorName": "Autor/Jméno",
|
||||||
@ -125,7 +124,7 @@
|
|||||||
"appearance": "Vzhled",
|
"appearance": "Vzhled",
|
||||||
"showWebInAppView": "Zobrazit zdrojové webové stránky v zobrazení aplikace",
|
"showWebInAppView": "Zobrazit zdrojové webové stránky v zobrazení aplikace",
|
||||||
"pinUpdates": "Připnout aplikace s aktualizacemi nahoru",
|
"pinUpdates": "Připnout aplikace s aktualizacemi nahoru",
|
||||||
"updates": "Updates",
|
"updates": "Aktualizace",
|
||||||
"sourceSpecific": "Specifické pro zdroj",
|
"sourceSpecific": "Specifické pro zdroj",
|
||||||
"appSource": "Zdroj aplikace",
|
"appSource": "Zdroj aplikace",
|
||||||
"noLogs": "Žádné protokoly",
|
"noLogs": "Žádné protokoly",
|
||||||
@ -162,7 +161,7 @@
|
|||||||
"errorWithHttpStatusCode": "Chyba {}",
|
"errorWithHttpStatusCode": "Chyba {}",
|
||||||
"versionCorrectionDisabled": "Oprava verze zakázána (zásuvný modul zřejmě nefunguje)",
|
"versionCorrectionDisabled": "Oprava verze zakázána (zásuvný modul zřejmě nefunguje)",
|
||||||
"unknown": "Neznám",
|
"unknown": "Neznám",
|
||||||
"none": "None",
|
"none": "Žádný",
|
||||||
"never": "Nikdy",
|
"never": "Nikdy",
|
||||||
"latestVersionX": "Nejnovější verze: {}",
|
"latestVersionX": "Nejnovější verze: {}",
|
||||||
"installedVersionX": "Nainstalovaná verze: {}",
|
"installedVersionX": "Nainstalovaná verze: {}",
|
||||||
@ -171,14 +170,13 @@
|
|||||||
"yesMarkUpdated": "Ano, označit jako aktualizované",
|
"yesMarkUpdated": "Ano, označit jako aktualizované",
|
||||||
"fdroid": "Oficiální repozitář F-Droid",
|
"fdroid": "Oficiální repozitář F-Droid",
|
||||||
"appIdOrName": "ID nebo název apky",
|
"appIdOrName": "ID nebo název apky",
|
||||||
"appId": "App ID",
|
"appId": "ID aplikace",
|
||||||
"appWithIdOrNameNotFound": "Žádná aplikace s tímto ID nebo názvem nebyla nalezena",
|
"appWithIdOrNameNotFound": "Žádná aplikace s tímto ID nebo názvem nebyla nalezena",
|
||||||
"reposHaveMultipleApps": "Repozitáře mohou obsahovat více aplikací",
|
"reposHaveMultipleApps": "Repozitáře mohou obsahovat více aplikací",
|
||||||
"fdroidThirdPartyRepo": "F-Droid repozitář třetí strany",
|
"fdroidThirdPartyRepo": "F-Droid repozitář třetí strany",
|
||||||
"steam": "Steam",
|
|
||||||
"steamMobile": "Steam Mobile",
|
"steamMobile": "Steam Mobile",
|
||||||
"steamChat": "Steam Chat",
|
"steamChat": "Steam Chat",
|
||||||
"install": "Install",
|
"install": "Nainstalujte",
|
||||||
"markInstalled": "Označit jako nainstalovaný",
|
"markInstalled": "Označit jako nainstalovaný",
|
||||||
"update": "Aktualizovat",
|
"update": "Aktualizovat",
|
||||||
"markUpdated": "Označit jako aktuální",
|
"markUpdated": "Označit jako aktuální",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Změny",
|
"changes": "Změny",
|
||||||
"releaseDate": "Datum vydání",
|
"releaseDate": "Datum vydání",
|
||||||
"importFromURLsInFile": "Importovat adresy URL ze souboru (např. OPML)",
|
"importFromURLsInFile": "Importovat adresy URL ze souboru (např. OPML)",
|
||||||
|
"versionDetectionExplanation": "Sloučit řetězec verze s verzí zjištěnou z OS",
|
||||||
"versionDetection": "Detekce verze",
|
"versionDetection": "Detekce verze",
|
||||||
"standardVersionDetection": "Standardní detekce verze",
|
"standardVersionDetection": "Standardní detekce verze",
|
||||||
"groupByCategory": "Seskupit podle kategorie",
|
"groupByCategory": "Seskupit podle kategorie",
|
||||||
@ -240,7 +239,7 @@
|
|||||||
"customLinkFilterRegex": "Vlastní filtr odkazů APK podle regulárního výrazu (výchozí '.apk$')",
|
"customLinkFilterRegex": "Vlastní filtr odkazů APK podle regulárního výrazu (výchozí '.apk$')",
|
||||||
"appsPossiblyUpdated": "Byly provedeny pokusy o aktualizaci aplikací",
|
"appsPossiblyUpdated": "Byly provedeny pokusy o aktualizaci aplikací",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Upozorňuje uživatele, že na pozadí mohly být provedeny aktualizace jedné nebo více aplikací",
|
"appsPossiblyUpdatedNotifDescription": "Upozorňuje uživatele, že na pozadí mohly být provedeny aktualizace jedné nebo více aplikací",
|
||||||
"xWasPossiblyUpdatedToY":"{} mohlo být aktualizováno na {}.",
|
"xWasPossiblyUpdatedToY": "{} mohlo být aktualizováno na {}.",
|
||||||
"enableBackgroundUpdates": "Povolit aktualizace na pozadí",
|
"enableBackgroundUpdates": "Povolit aktualizace na pozadí",
|
||||||
"backgroundUpdateReqsExplanation": "Aktualizace na pozadí nemusí být možná pro všechny aplikace.",
|
"backgroundUpdateReqsExplanation": "Aktualizace na pozadí nemusí být možná pro všechny aplikace.",
|
||||||
"backgroundUpdateLimitsExplanation": "Úspěšnost instalace na pozadí lze určit pouze v případě, že je otevřeno Obtainium.",
|
"backgroundUpdateLimitsExplanation": "Úspěšnost instalace na pozadí lze určit pouze v případě, že je otevřeno Obtainium.",
|
||||||
@ -284,9 +283,24 @@
|
|||||||
"parallelDownloads": "Povolit souběžné stahování",
|
"parallelDownloads": "Povolit souběžné stahování",
|
||||||
"installMethod": "Metoda instalace",
|
"installMethod": "Metoda instalace",
|
||||||
"normal": "Normální",
|
"normal": "Normální",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Správce",
|
"root": "Správce",
|
||||||
"shizukuBinderNotFound": "Shizuku neběží",
|
"shizukuBinderNotFound": "Shizuku neběží",
|
||||||
|
"useSystemFont": "Použít systémové písmo",
|
||||||
|
"systemFontError": "Chyba při načítání systémového písma: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Použít kód verze aplikace jako verzi zjištěnou OS",
|
||||||
|
"requestHeader": "Hlavička požadavku",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Použít poslední nahrané dílo jako datum vydání",
|
||||||
|
"defaultPseudoVersioningMethod": "Výchozí metoda pseudoverze",
|
||||||
|
"partialAPKHash": "Částečný hash APK",
|
||||||
|
"APKLinkHash": "Odkaz APK Hash",
|
||||||
|
"directAPKLink": "Přímý odkaz APK",
|
||||||
|
"pseudoVersionInUse": "Pseudoverze se používá",
|
||||||
|
"installed": "Instalováno",
|
||||||
|
"latest": "Nejnovější",
|
||||||
|
"invertRegEx": "Invertovat regulární výraz",
|
||||||
|
"note": "Poznámka",
|
||||||
|
"selfHostedNote": "Rozbalovací seznam \"{}\" lze použít k dosažení vlastních/obvyklých instancí libovolného zdroje.",
|
||||||
|
"badDownload": "APK nelze analyzovat (nekompatibilní nebo částečné stažení)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Odstranit Apku?",
|
"one": "Odstranit Apku?",
|
||||||
"other": "Odstranit Apky?"
|
"other": "Odstranit Apky?"
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"placeholder": "Platzhalter",
|
"placeholder": "Platzhalter",
|
||||||
"someErrors": "Es traten einige Fehler auf",
|
"someErrors": "Es traten einige Fehler auf",
|
||||||
"unexpectedError": "Unerwarteter Fehler",
|
"unexpectedError": "Unerwarteter Fehler",
|
||||||
"ok": "Okay",
|
"ok": "OK",
|
||||||
"and": "und",
|
"and": "und",
|
||||||
"githubPATLabel": "GitHub Personal Access Token (Erhöht das Ratenlimit)",
|
"githubPATLabel": "GitHub Personal Access Token (Erhöht das Ratenlimit)",
|
||||||
"includePrereleases": "Vorabversionen einbeziehen",
|
"includePrereleases": "Vorabversionen einbeziehen",
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"app": "App",
|
"app": "App",
|
||||||
"appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zum Nachverfolgen.",
|
"appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zum Nachverfolgen.",
|
||||||
"youPickedTrackOnly": "Sie haben die Option „Nur Nachverfolgen“ gewählt.",
|
"youPickedTrackOnly": "Sie haben die Option „Nur Nachverfolgen“ gewählt.",
|
||||||
"trackOnlyAppDescription": "Die App wird auf Updates überwacht, aber Obtainium wird sie nicht herunterladen oder installieren.",
|
"trackOnlyAppDescription": "Die App wird auf Aktualisierungen überwacht, aber Obtainium wird sie nicht herunterladen oder installieren.",
|
||||||
"cancelled": "Abgebrochen",
|
"cancelled": "Abgebrochen",
|
||||||
"appAlreadyAdded": "App bereits hinzugefügt",
|
"appAlreadyAdded": "App bereits hinzugefügt",
|
||||||
"alreadyUpToDateQuestion": "App bereits auf dem neuesten Stand?",
|
"alreadyUpToDateQuestion": "App bereits auf dem neuesten Stand?",
|
||||||
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Fortschritt: {}%",
|
"percentProgress": "Fortschritt: {}%",
|
||||||
"pleaseWait": "Bitte warten",
|
"pleaseWait": "Bitte warten",
|
||||||
"updateAvailable": "Aktualisierung verfügbar",
|
"updateAvailable": "Aktualisierung verfügbar",
|
||||||
"estimateInBracketsShort": "(ca.)",
|
|
||||||
"notInstalled": "Nicht installiert",
|
"notInstalled": "Nicht installiert",
|
||||||
"estimateInBrackets": "(Ungefähr)",
|
"pseudoVersion": "Pseudoversion",
|
||||||
"selectAll": "Alle auswählen",
|
"selectAll": "Alle auswählen",
|
||||||
"deselectX": "{} abgewählt",
|
"deselectX": "{} abgewählt",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} wird aus Obtainium entfernt, bleibt aber auf dem Gerät installiert.",
|
"xWillBeRemovedButRemainInstalled": "{} wird aus Obtainium entfernt, bleibt aber auf dem Gerät installiert.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "„Oben anheften“ aufheben",
|
"unpinFromTop": "„Oben anheften“ aufheben",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Installationsstatus für ausgewählte Apps zurücksetzen?",
|
"resetInstallStatusForSelectedAppsQuestion": "Installationsstatus für ausgewählte Apps zurücksetzen?",
|
||||||
"installStatusOfXWillBeResetExplanation": "Der Installationsstatus der ausgewählten Apps wird zurückgesetzt. Dies kann hilfreich sein, wenn die in Obtainium angezeigte App-Version aufgrund fehlgeschlagener Aktualisierungen oder anderer Probleme falsch ist.",
|
"installStatusOfXWillBeResetExplanation": "Der Installationsstatus der ausgewählten Apps wird zurückgesetzt. Dies kann hilfreich sein, wenn die in Obtainium angezeigte App-Version aufgrund fehlgeschlagener Aktualisierungen oder anderer Probleme falsch ist.",
|
||||||
|
"customLinkMessage": "Diese Links funktionieren auf Geräten, wo Obtainium installiert ist",
|
||||||
|
"shareAppConfigLinks": "Teile die Appkonfiguration als HTML-Link",
|
||||||
"shareSelectedAppURLs": "Ausgewählte App-URLs teilen",
|
"shareSelectedAppURLs": "Ausgewählte App-URLs teilen",
|
||||||
"resetInstallStatus": "Installationsstatus zurücksetzen",
|
"resetInstallStatus": "Installationsstatus zurücksetzen",
|
||||||
"more": "Mehr",
|
"more": "Mehr",
|
||||||
@ -88,17 +89,17 @@
|
|||||||
"importExport": "Import/Export",
|
"importExport": "Import/Export",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
"exportedTo": "Exportiert zu {}",
|
"exportedTo": "Exportiert zu {}",
|
||||||
"obtainiumExport": "Obtainium Export",
|
"obtainiumExport": "Obtainium-Export",
|
||||||
"invalidInput": "Ungültige Eingabe",
|
"invalidInput": "Ungültige Eingabe",
|
||||||
"importedX": "Importiert {}",
|
"importedX": "Importiert {}",
|
||||||
"obtainiumImport": "Obtainium Import",
|
"obtainiumImport": "Obtainium-Import",
|
||||||
"importFromURLList": "Importieren aus URL-Liste",
|
"importFromURLList": "Importieren aus URL-Liste",
|
||||||
"searchQuery": "Suchanfrage",
|
"searchQuery": "Suchanfrage",
|
||||||
"appURLList": "App URL-Liste",
|
"appURLList": "App URL-Liste",
|
||||||
"line": "Linie",
|
"line": "Linie",
|
||||||
"searchX": "Suche {}",
|
"searchX": "Suche {}",
|
||||||
"noResults": "Keine Ergebnisse gefunden",
|
"noResults": "Keine Ergebnisse gefunden",
|
||||||
"importX": "Import {}",
|
"importX": "Importieren {}",
|
||||||
"importedAppsIdDisclaimer": "Importierte Apps werden möglicherweise fälschlicherweise als \"Nicht installiert\" angezeigt. Um dies zu beheben, installieren Sie sie erneut über Obtainium. Dies hat keine Auswirkungen auf App-Daten. Es betrifft nur URL- und Drittanbieter-Importmethoden.",
|
"importedAppsIdDisclaimer": "Importierte Apps werden möglicherweise fälschlicherweise als \"Nicht installiert\" angezeigt. Um dies zu beheben, installieren Sie sie erneut über Obtainium. Dies hat keine Auswirkungen auf App-Daten. Es betrifft nur URL- und Drittanbieter-Importmethoden.",
|
||||||
"importErrors": "Importfehler",
|
"importErrors": "Importfehler",
|
||||||
"importedXOfYApps": "{} von {} Apps importiert.",
|
"importedXOfYApps": "{} von {} Apps importiert.",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Dunkel",
|
"dark": "Dunkel",
|
||||||
"light": "Hell",
|
"light": "Hell",
|
||||||
"followSystem": "System folgen",
|
"followSystem": "System folgen",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Verwende Pure Black Dark Theme",
|
"useBlackTheme": "Verwende Pure Black Dark Theme",
|
||||||
"appSortBy": "App sortieren nach",
|
"appSortBy": "App sortieren nach",
|
||||||
"authorName": "Autor/Name",
|
"authorName": "Autor/Name",
|
||||||
@ -133,7 +132,7 @@
|
|||||||
"close": "Schließen",
|
"close": "Schließen",
|
||||||
"share": "Teilen",
|
"share": "Teilen",
|
||||||
"appNotFound": "App nicht gefunden",
|
"appNotFound": "App nicht gefunden",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"obtainiumExportHyphenatedLowercase": "Obtainium-Export",
|
||||||
"pickAnAPK": "APK auswählen",
|
"pickAnAPK": "APK auswählen",
|
||||||
"appHasMoreThanOnePackage": "{} verfügt über mehr als ein Paket:",
|
"appHasMoreThanOnePackage": "{} verfügt über mehr als ein Paket:",
|
||||||
"deviceSupportsXArch": "Ihr Gerät unterstützt die CPU-Architektur {}.",
|
"deviceSupportsXArch": "Ihr Gerät unterstützt die CPU-Architektur {}.",
|
||||||
@ -175,9 +174,8 @@
|
|||||||
"appWithIdOrNameNotFound": "Es wurde keine App mit dieser ID oder diesem Namen gefunden",
|
"appWithIdOrNameNotFound": "Es wurde keine App mit dieser ID oder diesem Namen gefunden",
|
||||||
"reposHaveMultipleApps": "Repos können mehrere Apps enthalten",
|
"reposHaveMultipleApps": "Repos können mehrere Apps enthalten",
|
||||||
"fdroidThirdPartyRepo": "F-Droid Drittparteienrepo",
|
"fdroidThirdPartyRepo": "F-Droid Drittparteienrepo",
|
||||||
"steam": "Steam",
|
|
||||||
"steamMobile": "Steam Mobile",
|
"steamMobile": "Steam Mobile",
|
||||||
"steamChat": "Steam Chat",
|
"steamChat": "Steam-Chat",
|
||||||
"install": "Installieren",
|
"install": "Installieren",
|
||||||
"markInstalled": "Als Installiert markieren",
|
"markInstalled": "Als Installiert markieren",
|
||||||
"update": "Aktualisieren",
|
"update": "Aktualisieren",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Änderungen",
|
"changes": "Änderungen",
|
||||||
"releaseDate": "Veröffentlichungsdatum",
|
"releaseDate": "Veröffentlichungsdatum",
|
||||||
"importFromURLsInFile": "Importieren von URLs aus Datei (z. B. OPML)",
|
"importFromURLsInFile": "Importieren von URLs aus Datei (z. B. OPML)",
|
||||||
|
"versionDetectionExplanation": "Abgleich der Versionsnummer mit der vom Betriebssystem erkannten Version",
|
||||||
"versionDetection": "Versionserkennung",
|
"versionDetection": "Versionserkennung",
|
||||||
"standardVersionDetection": "Standardversionserkennung",
|
"standardVersionDetection": "Standardversionserkennung",
|
||||||
"groupByCategory": "Nach Kategorie gruppieren",
|
"groupByCategory": "Nach Kategorie gruppieren",
|
||||||
@ -227,7 +226,7 @@
|
|||||||
"tryInferAppIdFromCode": "Versuche, die App-ID aus dem Quellcode zu ermitteln",
|
"tryInferAppIdFromCode": "Versuche, die App-ID aus dem Quellcode zu ermitteln",
|
||||||
"removeOnExternalUninstall": "Automatisches Entfernen von extern deinstallierten Apps",
|
"removeOnExternalUninstall": "Automatisches Entfernen von extern deinstallierten Apps",
|
||||||
"pickHighestVersionCode": "Automatische Auswahl des APK mit höchstem Versionscode",
|
"pickHighestVersionCode": "Automatische Auswahl des APK mit höchstem Versionscode",
|
||||||
"checkUpdateOnDetailPage": "Nach Updates suchen, wenn eine App-Detailseite geöffnet wird",
|
"checkUpdateOnDetailPage": "Nach Aktualisierungen suchen, wenn eine App-Detailseite geöffnet wird",
|
||||||
"disablePageTransitions": "Animationen für Seitenübergänge deaktivieren",
|
"disablePageTransitions": "Animationen für Seitenübergänge deaktivieren",
|
||||||
"reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge",
|
"reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge",
|
||||||
"minStarCount": "Minimale Anzahl von Sternen",
|
"minStarCount": "Minimale Anzahl von Sternen",
|
||||||
@ -239,7 +238,7 @@
|
|||||||
"filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern",
|
"filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern",
|
||||||
"customLinkFilterRegex": "Benutzerdefinierter APK Link Filter nach Regulärem Ausdruck (Standard '.apk$')",
|
"customLinkFilterRegex": "Benutzerdefinierter APK Link Filter nach Regulärem Ausdruck (Standard '.apk$')",
|
||||||
"appsPossiblyUpdated": "App Aktualisierungen wurden versucht",
|
"appsPossiblyUpdated": "App Aktualisierungen wurden versucht",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Benachrichtigt den Benutzer, dass Updates für eine oder mehrere Apps möglicherweise im Hintergrund durchgeführt wurden",
|
"appsPossiblyUpdatedNotifDescription": "Benachrichtigt den Benutzer, dass Aktualisierungen für eine oder mehrere Apps möglicherweise im Hintergrund durchgeführt wurden",
|
||||||
"xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.",
|
"xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.",
|
||||||
"enableBackgroundUpdates": "Aktiviere Hintergrundaktualisierungen",
|
"enableBackgroundUpdates": "Aktiviere Hintergrundaktualisierungen",
|
||||||
"backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.",
|
"backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.",
|
||||||
@ -269,7 +268,7 @@
|
|||||||
"runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen",
|
"runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen",
|
||||||
"versionExtractWholePage": "Versions-Extraktion per RegEx auf die gesamte Seite anwenden",
|
"versionExtractWholePage": "Versions-Extraktion per RegEx auf die gesamte Seite anwenden",
|
||||||
"installing": "Installiere",
|
"installing": "Installiere",
|
||||||
"skipUpdateNotifications": "Keine Benachrichtigung zu App-Updates geben",
|
"skipUpdateNotifications": "Keine Benachrichtigung zu App-Aktualisierungen geben",
|
||||||
"updatesAvailableNotifChannel": "Aktualisierungen verfügbar",
|
"updatesAvailableNotifChannel": "Aktualisierungen verfügbar",
|
||||||
"appsUpdatedNotifChannel": "Apps aktualisiert",
|
"appsUpdatedNotifChannel": "Apps aktualisiert",
|
||||||
"appsPossiblyUpdatedNotifChannel": "App Aktualisierungen wurden versucht",
|
"appsPossiblyUpdatedNotifChannel": "App Aktualisierungen wurden versucht",
|
||||||
@ -284,16 +283,31 @@
|
|||||||
"parallelDownloads": "Erlaube parallele Downloads",
|
"parallelDownloads": "Erlaube parallele Downloads",
|
||||||
"installMethod": "Installationsmethode",
|
"installMethod": "Installationsmethode",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Root",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "Shizuku läuft nicht",
|
"shizukuBinderNotFound": "Kompatibler Shizukudienst wurde nicht gefunden",
|
||||||
|
"useSystemFont": "Verwende die Systemschriftart",
|
||||||
|
"systemFontError": "Fehler beim Laden der Systemschriftart: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Verwende die Appversion als erkannte Version vom Betriebssystem",
|
||||||
|
"requestHeader": "Request Header",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Den letzten Asset-Upload als Veröffentlichungsdatum verwenden",
|
||||||
|
"defaultPseudoVersioningMethod": "Standardmäßiges Verfahren zur Pseudo-Versionierung",
|
||||||
|
"partialAPKHash": "partieller APK-Hash",
|
||||||
|
"APKLinkHash": "APK-Link-Hash",
|
||||||
|
"directAPKLink": "Direkter APK-Link",
|
||||||
|
"pseudoVersionInUse": "Es werden Pseudoversionen verwendet",
|
||||||
|
"installed": "Installiert",
|
||||||
|
"latest": "Neueste Version",
|
||||||
|
"invertRegEx": "Regulären Ausdruck invertieren",
|
||||||
|
"note": "Hinweis",
|
||||||
|
"selfHostedNote": "Das „{}“-Dropdown-Menü kann verwendet werden, um selbst gehostete/angepasste Instanzen einer beliebigen Quelle zu erreichen.",
|
||||||
|
"badDownload": "Die APK konnte nicht geparst werden (inkompatibler oder teilweiser Download)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "App entfernen?",
|
"one": "App entfernen?",
|
||||||
"other": "Apps entfernen?"
|
"other": "Apps entfernen?"
|
||||||
},
|
},
|
||||||
"tooManyRequestsTryAgainInMinutes": {
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
"one": "Zu viele Anfragen (Rate begrenzt) – versuchen Sie es in {} Minute erneut",
|
"one": "Zu viele Anfragen (Rate begrenzt) – versuche es in {} Minute erneut",
|
||||||
"other": "Zu viele Anfragen (Rate begrenzt) – versuchen Sie es in {} Minuten erneut"
|
"other": "Zu viele Anfragen (Rate begrenzt) – versuche es in {} Minuten erneut"
|
||||||
},
|
},
|
||||||
"bgUpdateGotErrorRetryInMinutes": {
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
"one": "Bei der Aktualisierungsprüfung im Hintergrund wurde ein {} festgestellt, eine erneute Prüfung wird in {} Minute geplant",
|
"one": "Bei der Aktualisierungsprüfung im Hintergrund wurde ein {} festgestellt, eine erneute Prüfung wird in {} Minute geplant",
|
||||||
@ -304,12 +318,12 @@
|
|||||||
"other": "Die Hintergrundaktualisierungsprüfung fand {} Aktualisierungen – benachrichtigt den Benutzer, falls erforderlich"
|
"other": "Die Hintergrundaktualisierungsprüfung fand {} Aktualisierungen – benachrichtigt den Benutzer, falls erforderlich"
|
||||||
},
|
},
|
||||||
"apps": {
|
"apps": {
|
||||||
"one": "{} App",
|
"eine": "{} App",
|
||||||
"other": "{} Apps"
|
"andere": "{} Apps"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"one": "{} URL",
|
"eine": "{} URL",
|
||||||
"other": "{} URLs"
|
"andere": "{} URLs"
|
||||||
},
|
},
|
||||||
"minute": {
|
"minute": {
|
||||||
"one": "{} Minute",
|
"one": "{} Minute",
|
||||||
|
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Progress: {}%",
|
"percentProgress": "Progress: {}%",
|
||||||
"pleaseWait": "Please Wait",
|
"pleaseWait": "Please Wait",
|
||||||
"updateAvailable": "Update Available",
|
"updateAvailable": "Update Available",
|
||||||
"estimateInBracketsShort": "(Est.)",
|
|
||||||
"notInstalled": "Not Installed",
|
"notInstalled": "Not Installed",
|
||||||
"estimateInBrackets": "(Estimate)",
|
"pseudoVersion": "pseudo-version",
|
||||||
"selectAll": "Select All",
|
"selectAll": "Select All",
|
||||||
"deselectX": "Deselect {}",
|
"deselectX": "Deselect {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.",
|
"xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.",
|
||||||
@ -73,13 +72,14 @@
|
|||||||
"unpinFromTop": "Unpin from top",
|
"unpinFromTop": "Unpin from top",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?",
|
"resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?",
|
||||||
"installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.",
|
"installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.",
|
||||||
|
"customLinkMessage": "These links work on devices with Obtainium installed",
|
||||||
|
"shareAppConfigLinks": "Share app configuration as HTML link",
|
||||||
"shareSelectedAppURLs": "Share Selected App URLs",
|
"shareSelectedAppURLs": "Share Selected App URLs",
|
||||||
"resetInstallStatus": "Reset Install Status",
|
"resetInstallStatus": "Reset Install Status",
|
||||||
"more": "More",
|
"more": "More",
|
||||||
"removeOutdatedFilter": "Remove Out-of-Date App Filter",
|
"removeOutdatedFilter": "Remove Out-of-Date App Filter",
|
||||||
"showOutdatedOnly": "Show Out-of-Date Apps Only",
|
"showOutdatedOnly": "Show Out-of-Date Apps Only",
|
||||||
"filter": "Filter",
|
"filter": "Filter",
|
||||||
"filterActive": "Filter *",
|
|
||||||
"filterApps": "Filter Apps",
|
"filterApps": "Filter Apps",
|
||||||
"appName": "App Name",
|
"appName": "App Name",
|
||||||
"author": "Author",
|
"author": "Author",
|
||||||
@ -110,8 +110,6 @@
|
|||||||
"dark": "Dark",
|
"dark": "Dark",
|
||||||
"light": "Light",
|
"light": "Light",
|
||||||
"followSystem": "Follow System",
|
"followSystem": "Follow System",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Use pure black dark theme",
|
"useBlackTheme": "Use pure black dark theme",
|
||||||
"appSortBy": "App Sort By",
|
"appSortBy": "App Sort By",
|
||||||
"authorName": "Author/Name",
|
"authorName": "Author/Name",
|
||||||
@ -164,8 +162,8 @@
|
|||||||
"unknown": "Unknown",
|
"unknown": "Unknown",
|
||||||
"none": "None",
|
"none": "None",
|
||||||
"never": "Never",
|
"never": "Never",
|
||||||
"latestVersionX": "Latest Version: {}",
|
"latestVersionX": "Latest: {}",
|
||||||
"installedVersionX": "Installed Version: {}",
|
"installedVersionX": "Installed: {}",
|
||||||
"lastUpdateCheckX": "Last Update Check: {}",
|
"lastUpdateCheckX": "Last Update Check: {}",
|
||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
"yesMarkUpdated": "Yes, Mark as Updated",
|
"yesMarkUpdated": "Yes, Mark as Updated",
|
||||||
@ -175,7 +173,6 @@
|
|||||||
"appWithIdOrNameNotFound": "No App was found with that ID or Name",
|
"appWithIdOrNameNotFound": "No App was found with that ID or Name",
|
||||||
"reposHaveMultipleApps": "Repos may contain multiple Apps",
|
"reposHaveMultipleApps": "Repos may contain multiple Apps",
|
||||||
"fdroidThirdPartyRepo": "F-Droid Third-Party Repo",
|
"fdroidThirdPartyRepo": "F-Droid Third-Party Repo",
|
||||||
"steam": "Steam",
|
|
||||||
"steamMobile": "Steam Mobile",
|
"steamMobile": "Steam Mobile",
|
||||||
"steamChat": "Steam Chat",
|
"steamChat": "Steam Chat",
|
||||||
"install": "Install",
|
"install": "Install",
|
||||||
@ -206,11 +203,12 @@
|
|||||||
"removeFromObtainium": "Remove from Obtainium",
|
"removeFromObtainium": "Remove from Obtainium",
|
||||||
"uninstallFromDevice": "Uninstall from Device",
|
"uninstallFromDevice": "Uninstall from Device",
|
||||||
"onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.",
|
"onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.",
|
||||||
"releaseDateAsVersion": "Use Release Date as Version",
|
"releaseDateAsVersion": "Use release date as version string",
|
||||||
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
||||||
"changes": "Changes",
|
"changes": "Changes",
|
||||||
"releaseDate": "Release Date",
|
"releaseDate": "Release Date",
|
||||||
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
|
"versionDetectionExplanation": "Reconcile version string with version detected from OS",
|
||||||
"versionDetection": "Version Detection",
|
"versionDetection": "Version Detection",
|
||||||
"standardVersionDetection": "Standard version detection",
|
"standardVersionDetection": "Standard version detection",
|
||||||
"groupByCategory": "Group by Category",
|
"groupByCategory": "Group by Category",
|
||||||
@ -252,8 +250,8 @@
|
|||||||
"exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)",
|
"exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)",
|
||||||
"bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
|
"bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
|
||||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
||||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
"versionExtractionRegEx": "Version String Extraction RegEx",
|
||||||
"matchGroupToUse": "Match Group to Use for Version Extraction Regex",
|
"matchGroupToUse": "Match Group to Use for Version String Extraction Regex",
|
||||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
"highlightTouchTargets": "Highlight less obvious touch targets",
|
||||||
"pickExportDir": "Pick Export Directory",
|
"pickExportDir": "Pick Export Directory",
|
||||||
"autoExportOnChanges": "Auto-export on changes",
|
"autoExportOnChanges": "Auto-export on changes",
|
||||||
@ -267,7 +265,7 @@
|
|||||||
"debugMenu": "Debug Menu",
|
"debugMenu": "Debug Menu",
|
||||||
"bgTaskStarted": "Background task started - check logs.",
|
"bgTaskStarted": "Background task started - check logs.",
|
||||||
"runBgCheckNow": "Run Background Update Check Now",
|
"runBgCheckNow": "Run Background Update Check Now",
|
||||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
"versionExtractWholePage": "Apply version string extraction Regex to entire page",
|
||||||
"installing": "Installing",
|
"installing": "Installing",
|
||||||
"skipUpdateNotifications": "Skip update notifications",
|
"skipUpdateNotifications": "Skip update notifications",
|
||||||
"updatesAvailableNotifChannel": "Updates Available",
|
"updatesAvailableNotifChannel": "Updates Available",
|
||||||
@ -284,11 +282,24 @@
|
|||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "Allow parallel downloads",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "Installation method",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Root",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "Сompatible Shizuku service wasn't found",
|
"shizukuBinderNotFound": "Сompatible Shizuku service wasn't found",
|
||||||
"useSystemFont": "Use the system font",
|
"useSystemFont": "Use the system font",
|
||||||
"systemFontError": "Error loading the system font: {}",
|
"systemFontError": "Error loading the system font: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
|
||||||
|
"requestHeader": "Request header",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
|
||||||
|
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
|
||||||
|
"partialAPKHash": "Partial APK Hash",
|
||||||
|
"APKLinkHash": "APK Link Hash",
|
||||||
|
"directAPKLink": "Direct APK Link",
|
||||||
|
"pseudoVersionInUse": "A Pseudo-Version is in Use",
|
||||||
|
"installed": "Installed",
|
||||||
|
"latest": "Latest",
|
||||||
|
"invertRegEx": "Invert regular expression",
|
||||||
|
"note": "Note",
|
||||||
|
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
|
||||||
|
"badDownload": "The APK could not be parsed (incompatible or partial download)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Remove App?",
|
"one": "Remove App?",
|
||||||
"other": "Remove Apps?"
|
"other": "Remove Apps?"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"invalidURLForSource": "URL de la aplicación {} no válida",
|
"invalidURLForSource": "URL de la aplicación {} no es válida",
|
||||||
"noReleaseFound": "No se ha podido encontrar una versión válida",
|
"noReleaseFound": "No se ha podido encontrar una versión válida",
|
||||||
"noVersionFound": "No se ha podido determinar la versión de la publicación",
|
"noVersionFound": "No se ha podido determinar la versión",
|
||||||
"urlMatchesNoSource": "La URL no coincide con ninguna fuente conocida",
|
"urlMatchesNoSource": "La URL no coincide con ninguna fuente conocida",
|
||||||
"cantInstallOlderVersion": "No se puede instalar una versión previa de la aplicación",
|
"cantInstallOlderVersion": "No se puede instalar una versión previa de la aplicación",
|
||||||
"appIdMismatch": "La ID del paquete descargado no coincide con la ID de la aplicación instalada",
|
"appIdMismatch": "La ID del paquete descargado no coincide con la ID de la aplicación instalada",
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"unexpectedError": "Error inesperado",
|
"unexpectedError": "Error inesperado",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"and": "y",
|
"and": "y",
|
||||||
"githubPATLabel": "Token GitHub de acceso personal\n(reduce tiempos de espera)",
|
"githubPATLabel": "Token de acceso personal a GitHub\n(reduce tiempos de espera)",
|
||||||
"includePrereleases": "Incluir versiones preliminares",
|
"includePrereleases": "Incluir versiones preliminares",
|
||||||
"fallbackToOlderReleases": "Retroceder a versiones previas",
|
"fallbackToOlderReleases": "Retroceder a versiones previas",
|
||||||
"filterReleaseTitlesByRegEx": "Filtrar por título de versión",
|
"filterReleaseTitlesByRegEx": "Filtrar por título de versión",
|
||||||
@ -22,20 +22,20 @@
|
|||||||
"requiredInBrackets": "(Requerido)",
|
"requiredInBrackets": "(Requerido)",
|
||||||
"dropdownNoOptsError": "ERROR: EL DESPLEGABLE DEBE TENER AL MENOS UNA OPCIÓN",
|
"dropdownNoOptsError": "ERROR: EL DESPLEGABLE DEBE TENER AL MENOS UNA OPCIÓN",
|
||||||
"colour": "Color",
|
"colour": "Color",
|
||||||
"githubStarredRepos": "Repositorios favoritos GitHub",
|
"githubStarredRepos": "Repositorios favoritos en GitHub",
|
||||||
"uname": "Nombre de usuario",
|
"uname": "Nombre de usuario",
|
||||||
"wrongArgNum": "Número de argumentos provistos inválido",
|
"wrongArgNum": "Número de argumentos provistos inválido",
|
||||||
"xIsTrackOnly": "{} es de 'Sólo seguimiento'",
|
"xIsTrackOnly": "{} es de 'sólo seguimiento'",
|
||||||
"source": "Origen",
|
"source": "Origen",
|
||||||
"app": "Aplicación",
|
"app": "Aplicación",
|
||||||
"appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'solo seguimiento'.",
|
"appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'solo seguimiento'.",
|
||||||
"youPickedTrackOnly": "Debe seleccionar la opción de 'solo seguimiento'.",
|
"youPickedTrackOnly": "Debe seleccionar la opción de 'solo seguimiento'.",
|
||||||
"trackOnlyAppDescription": "Se hará el seguimiento de actualizaciones para la aplicación, pero Obtainium no será capaz de descargarla o actalizarla.",
|
"trackOnlyAppDescription": "Se hará el seguimiento de actualizaciones para la aplicación, pero Obtainium no será capaz de descargar o actualizarla.",
|
||||||
"cancelled": "Cancelado",
|
"cancelled": "Cancelado",
|
||||||
"appAlreadyAdded": "Aplicación ya añadida",
|
"appAlreadyAdded": "Aplicación añadida anteriormente",
|
||||||
"alreadyUpToDateQuestion": "¿Aplicación ya actualizada?",
|
"alreadyUpToDateQuestion": "¿Aplicación actualizada previamente?",
|
||||||
"addApp": "Añadir Aplicación",
|
"addApp": "Añadir Aplicación",
|
||||||
"appSourceURL": "URL de Origen de la Aplicación",
|
"appSourceURL": "URL de origen de la aplicación",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"add": "Añadir",
|
"add": "Añadir",
|
||||||
"searchSomeSourcesLabel": "Buscar (solo algunas fuentes)",
|
"searchSomeSourcesLabel": "Buscar (solo algunas fuentes)",
|
||||||
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Progreso: {}%",
|
"percentProgress": "Progreso: {}%",
|
||||||
"pleaseWait": "Por favor, espere",
|
"pleaseWait": "Por favor, espere",
|
||||||
"updateAvailable": "Actualización Disponible",
|
"updateAvailable": "Actualización Disponible",
|
||||||
"estimateInBracketsShort": "(Aprox.)",
|
|
||||||
"notInstalled": "No Instalado",
|
"notInstalled": "No Instalado",
|
||||||
"estimateInBrackets": "(Aproximado)",
|
"pseudoVersion": "pseudoversión",
|
||||||
"selectAll": "Seleccionar Todo",
|
"selectAll": "Seleccionar Todo",
|
||||||
"deselectX": "Deseleccionar {}",
|
"deselectX": "Deseleccionar {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} será eliminada de Obtainium pero continuará instalada en el dispositivo.",
|
"xWillBeRemovedButRemainInstalled": "{} será eliminada de Obtainium pero continuará instalada en el dispositivo.",
|
||||||
@ -72,9 +71,11 @@
|
|||||||
"pinToTop": "Fijar arriba",
|
"pinToTop": "Fijar arriba",
|
||||||
"unpinFromTop": "Desfijar de arriba",
|
"unpinFromTop": "Desfijar de arriba",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "¿Restuarar estado de instalación para las aplicaciones seleccionadas?",
|
"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 útil cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.",
|
"installStatusOfXWillBeResetExplanation": "Se restaurará el estado de instalación de las aplicaciones seleccionadas.\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.",
|
||||||
|
"customLinkMessage": "Estos enlaces funcionan en dispositivos con Obtainium instalado",
|
||||||
|
"shareAppConfigLinks": "Compartir la configuración de la aplicación como enlace HTML",
|
||||||
"shareSelectedAppURLs": "Compartir URLs de las aplicaciones seleccionadas",
|
"shareSelectedAppURLs": "Compartir URLs de las aplicaciones seleccionadas",
|
||||||
"resetInstallStatus": "Restaurar Estado de Instalación",
|
"resetInstallStatus": "Restaurar estado de instalación",
|
||||||
"more": "Más",
|
"more": "Más",
|
||||||
"removeOutdatedFilter": "Elimiar filtro de aplicaciones desactualizado",
|
"removeOutdatedFilter": "Elimiar filtro de aplicaciones desactualizado",
|
||||||
"showOutdatedOnly": "Mostrar solo aplicaciones desactualizadas",
|
"showOutdatedOnly": "Mostrar solo aplicaciones desactualizadas",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Oscuro",
|
"dark": "Oscuro",
|
||||||
"light": "Claro",
|
"light": "Claro",
|
||||||
"followSystem": "Seguir al sistema",
|
"followSystem": "Seguir al sistema",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Negro puro en tema Oscuro",
|
"useBlackTheme": "Negro puro en tema Oscuro",
|
||||||
"appSortBy": "Ordenar Apps Por",
|
"appSortBy": "Ordenar Apps Por",
|
||||||
"authorName": "Autor/Nombre",
|
"authorName": "Autor/Nombre",
|
||||||
@ -124,7 +123,7 @@
|
|||||||
"neverManualOnly": "Nunca, solo manual",
|
"neverManualOnly": "Nunca, solo manual",
|
||||||
"appearance": "Apariencia",
|
"appearance": "Apariencia",
|
||||||
"showWebInAppView": "Mostrar vista de la web de origen",
|
"showWebInAppView": "Mostrar vista de la web de origen",
|
||||||
"pinUpdates": "Fijar Actualizaciones al principio",
|
"pinUpdates": "Fijar actualizaciones al principio",
|
||||||
"updates": "Actualizaciones",
|
"updates": "Actualizaciones",
|
||||||
"sourceSpecific": "Fuente Específica",
|
"sourceSpecific": "Fuente Específica",
|
||||||
"appSource": "Obtainium en GitHub",
|
"appSource": "Obtainium en GitHub",
|
||||||
@ -133,7 +132,7 @@
|
|||||||
"close": "Cerrar",
|
"close": "Cerrar",
|
||||||
"share": "Compartir",
|
"share": "Compartir",
|
||||||
"appNotFound": "Aplicación no encontrada",
|
"appNotFound": "Aplicación no encontrada",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"obtainiumExportHyphenatedLowercase": "obtainium-exportación",
|
||||||
"pickAnAPK": "Seleccione una APK",
|
"pickAnAPK": "Seleccione una APK",
|
||||||
"appHasMoreThanOnePackage": "{} tiene más de un paquete:",
|
"appHasMoreThanOnePackage": "{} tiene más de un paquete:",
|
||||||
"deviceSupportsXArch": "Su dispositivo soporta las siguientes arquitecturas de procesador: {}.",
|
"deviceSupportsXArch": "Su dispositivo soporta las siguientes arquitecturas de procesador: {}.",
|
||||||
@ -141,77 +140,77 @@
|
|||||||
"warning": "Aviso",
|
"warning": "Aviso",
|
||||||
"sourceIsXButPackageFromYPrompt": "La fuente de la aplicación es '{}' pero el paquete de la actualización viene de '{}'. ¿Desea continuar?",
|
"sourceIsXButPackageFromYPrompt": "La fuente de la aplicación es '{}' pero el paquete de la actualización viene de '{}'. ¿Desea continuar?",
|
||||||
"updatesAvailable": "Actualizaciones Disponibles",
|
"updatesAvailable": "Actualizaciones Disponibles",
|
||||||
"updatesAvailableNotifDescription": "Notifica al usuario de que hay actualizaciones para una o más aplicaciones monitorizadas por Obtainium",
|
"updatesAvailableNotifDescription": "Notifica al usuario de que hay actualizaciones para una o más aplicaciones monitoreadas por Obtainium",
|
||||||
"noNewUpdates": "No hay nuevas actualizaciones.",
|
"noNewUpdates": "No hay nuevas actualizaciones.",
|
||||||
"xHasAnUpdate": "{} tiene una actualización.",
|
"xHasAnUpdate": "{} tiene una actualización.",
|
||||||
"appsUpdated": "Aplicaciones Actualizadas",
|
"appsUpdated": "Aplicaciones actualizadas",
|
||||||
"appsUpdatedNotifDescription": "Notifica al usuario de que una o más aplicaciones han sido actualizadas en segundo plano",
|
"appsUpdatedNotifDescription": "Notifica al usuario de que una o más aplicaciones han sido actualizadas en segundo plano",
|
||||||
"xWasUpdatedToY": "{} ha sido actualizada a {}.",
|
"xWasUpdatedToY": "{} ha sido actualizada a {}.",
|
||||||
"errorCheckingUpdates": "Error Buscando Actualizaciones",
|
"errorCheckingUpdates": "Error buscando ectualizaciones",
|
||||||
"errorCheckingUpdatesNotifDescription": "Una notificación que muestra cuándo la comprobación de actualizaciones en segundo plano falla",
|
"errorCheckingUpdatesNotifDescription": "Una notificación que muestra cuándo la comprobación de actualizaciones en segundo plano falla",
|
||||||
"appsRemoved": "Aplicaciones Eliminadas",
|
"appsRemoved": "Aplicaciones eliminadas",
|
||||||
"appsRemovedNotifDescription": "Notifica al usuario que una o más aplicaciones fueron eliminadas por problemas al cargarlas",
|
"appsRemovedNotifDescription": "Notifica al usuario que una o más aplicaciones fueron eliminadas por problemas al cargarlas",
|
||||||
"xWasRemovedDueToErrorY": "{} ha sido eliminada por: {}",
|
"xWasRemovedDueToErrorY": "{} ha sido eliminada por: {}",
|
||||||
"completeAppInstallation": "Instalación Completa de la Aplicación",
|
"completeAppInstallation": "Instalación completa de la aplicación",
|
||||||
"obtainiumMustBeOpenToInstallApps": "Obtainium debe estar abierto para instalar aplicaciones",
|
"obtainiumMustBeOpenToInstallApps": "Obtainium debe estar abierto para instalar aplicaciones",
|
||||||
"completeAppInstallationNotifDescription": "Pide al usuario volver a Obtainium para terminar de instalar una aplicación",
|
"completeAppInstallationNotifDescription": "Pide al usuario volver a Obtainium para terminar de instalar una aplicación",
|
||||||
"checkingForUpdates": "Buscando Actualizaciones",
|
"checkingForUpdates": "Buscando actualizaciones...",
|
||||||
"checkingForUpdatesNotifDescription": "Notificación temporal que aparece al buscar actualizaciones",
|
"checkingForUpdatesNotifDescription": "Notificación temporal que aparece al buscar actualizaciones",
|
||||||
"pleaseAllowInstallPerm": "Por favor, permita que Obtainium instale aplicaciones",
|
"pleaseAllowInstallPerm": "Por favor, permita que Obtainium instale aplicaciones",
|
||||||
"trackOnly": "Solo Seguimiento",
|
"trackOnly": "Solo para seguimiento",
|
||||||
"errorWithHttpStatusCode": "Error {}",
|
"errorWithHttpStatusCode": "Error {}",
|
||||||
"versionCorrectionDisabled": "Corrección de versiones desactivada (el plugin parece no funcionar)",
|
"versionCorrectionDisabled": "Corrección de versiones desactivada (el plugin parece no funcionar)",
|
||||||
"unknown": "Desconocido",
|
"unknown": "Desconocido",
|
||||||
"none": "Ninguno",
|
"none": "Ninguno",
|
||||||
"never": "Nunca",
|
"never": "Nunca",
|
||||||
"latestVersionX": "Última Versión: {}",
|
"latestVersionX": "Última versión: {}",
|
||||||
"installedVersionX": "Versión Instalada: {}",
|
"installedVersionX": "Versión instalada: {}",
|
||||||
"lastUpdateCheckX": "Última Comprobación: {}",
|
"lastUpdateCheckX": "Última comprobación: {}",
|
||||||
"remove": "Eliminar",
|
"remove": "Eliminar",
|
||||||
"yesMarkUpdated": "Sí, Marcar como Actualizada",
|
"yesMarkUpdated": "Sí, marcar como actualizada",
|
||||||
"fdroid": "Repositorio oficial F-Droid",
|
"fdroid": "Repositorio oficial F-Droid",
|
||||||
"appIdOrName": "ID o Nombre de la Aplicación",
|
"appIdOrName": "ID o Nombre de la Aplicación",
|
||||||
"appId": "ID de la Aplicación",
|
"appId": "ID de la Aplicación",
|
||||||
"appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre",
|
"appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre",
|
||||||
"reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones",
|
"reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones",
|
||||||
"fdroidThirdPartyRepo": "Rpositorios de terceros F-Droid",
|
"fdroidThirdPartyRepo": "Repositorio de tercera parte F-Droid",
|
||||||
"steam": "Steam",
|
"steamMobile": "Móvil de vapor",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "Chat de vapor",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "Instalar",
|
"install": "Instalar",
|
||||||
"markInstalled": "Marcar como Instalada",
|
"markInstalled": "Marcar como instalada",
|
||||||
"update": "Actualizar",
|
"update": "Actualizar",
|
||||||
"markUpdated": "Marcar como Actualizada",
|
"markUpdated": "Marcar como actualizada",
|
||||||
"additionalOptions": "Opciones Adicionales",
|
"additionalOptions": "Opciones adicionales",
|
||||||
"disableVersionDetection": "Descativar Detección de Versiones",
|
"disableVersionDetection": "Desactivar la 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.",
|
"noVersionDetectionExplanation": "Esta opción solo se debe usar en aplicaciones en las que la deteción de versiones pueda que no funcionar correctamente.",
|
||||||
"downloadingX": "Descargando {}",
|
"downloadingX": "Descargando {}",
|
||||||
"downloadNotifDescription": "Notifica al usuario del progreso de descarga de una aplicación",
|
"downloadNotifDescription": "Notifica al usuario del progreso de descarga de una aplicación",
|
||||||
"noAPKFound": "APK no encontrada",
|
"noAPKFound": "No se encontró el paquete de instalación APK",
|
||||||
"noVersionDetection": "Sin detección de versiones",
|
"noVersionDetection": "Sin detección de versiones",
|
||||||
"categorize": "Catogorizar",
|
"categorize": "Catogorizar",
|
||||||
"categories": "Categorías",
|
"categories": "Categorías",
|
||||||
"category": "Categoría",
|
"category": "Categoría",
|
||||||
"noCategory": "Sin Categoría",
|
"noCategory": "Sin categoría",
|
||||||
"noCategories": "Sin Categorías",
|
"noCategories": "Sin categorías",
|
||||||
"deleteCategoriesQuestion": "¿Eliminar Categorías?",
|
"deleteCategoriesQuestion": "¿Eliminar categorías?",
|
||||||
"categoryDeleteWarning": "Todas las aplicaciones en las categorías eliminadas serán marcadas como 'Sin Categoría'.",
|
"categoryDeleteWarning": "Todas las aplicaciones en las categorías eliminadas serán marcadas como 'Sin categoría'.",
|
||||||
"addCategory": "Añadir Categoría",
|
"addCategory": "Añadir categoría",
|
||||||
"label": "Nombre",
|
"label": "Nombre",
|
||||||
"language": "Idioma",
|
"language": "Idioma",
|
||||||
"copiedToClipboard": "Copiado al Portapapeles",
|
"copiedToClipboard": "Copiado al portapapeles",
|
||||||
"storagePermissionDenied": "Permiso de Almacenamiento rechazado",
|
"storagePermissionDenied": "Permiso de almacenamiento rechazado",
|
||||||
"selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaciones seleccionadas.",
|
"selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaciones seleccionadas.",
|
||||||
"filterAPKsByRegEx": "Filtrar por APKs",
|
"filterAPKsByRegEx": "Filtrar por APKs",
|
||||||
"removeFromObtainium": "Eliminar de Obtainium",
|
"removeFromObtainium": "Eliminar de Obtainium",
|
||||||
"uninstallFromDevice": "Desinstalar del Dispositivo",
|
"uninstallFromDevice": "Desinstalar del dispositivo",
|
||||||
"onlyWorksWithNonVersionDetectApps": "Solo funciona para aplicaciones con la detección de versiones desactivada.",
|
"onlyWorksWithNonVersionDetectApps": "Solo funciona para aplicaciones con la detección de versiones desactivada.",
|
||||||
"releaseDateAsVersion": "Por fecha de publicación",
|
"releaseDateAsVersion": "Por fecha de publicación",
|
||||||
"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.",
|
"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",
|
"changes": "Cambios",
|
||||||
"releaseDate": "Fecha de Publicación",
|
"releaseDate": "Fecha de publicación",
|
||||||
"importFromURLsInFile": "Importar URLs desde archivo (como OPML)",
|
"importFromURLsInFile": "Importar URLs desde archivo (como OPML)",
|
||||||
"versionDetection": "Detección de Versiones",
|
"versionDetectionExplanation": "Conciliar la cadena de versión con la versión detectada desde el sistema operativo",
|
||||||
|
"versionDetection": "Detección de versiones",
|
||||||
"standardVersionDetection": "Por versión",
|
"standardVersionDetection": "Por versión",
|
||||||
"groupByCategory": "Agrupar por categoría",
|
"groupByCategory": "Agrupar por categoría",
|
||||||
"autoApkFilterByArch": "Filtrar APKs por arquitectura del procesador (si es posible)",
|
"autoApkFilterByArch": "Filtrar APKs por arquitectura del procesador (si es posible)",
|
||||||
@ -220,25 +219,25 @@
|
|||||||
"dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps en 'solo seguimiento'",
|
"dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps en 'solo seguimiento'",
|
||||||
"dontShowAPKOriginWarnings": "No mostrar avisos sobre las fuentes de las APKs",
|
"dontShowAPKOriginWarnings": "No mostrar avisos sobre las fuentes de las APKs",
|
||||||
"moveNonInstalledAppsToBottom": "Mover Apps no instaladas al final",
|
"moveNonInstalledAppsToBottom": "Mover Apps no instaladas al final",
|
||||||
"gitlabPATLabel": "Token GitLab de acceso personal\n(habilita la búsqueda y mejor detección de APKs)",
|
"gitlabPATLabel": "Token de acceso personal a GitLab\n(habilita la búsqueda y mejor detección de APKs)",
|
||||||
"about": "Acerca",
|
"about": "Acerca",
|
||||||
"requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en ajustes)",
|
"requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en ajustes)",
|
||||||
"checkOnStart": "Comprobar actualizaciones al inicio",
|
"checkOnStart": "Comprobar actualizaciones al inicio",
|
||||||
"tryInferAppIdFromCode": "Intentar deducir la ID de la app por el código fuente",
|
"tryInferAppIdFromCode": "Intentar deducir la ID de la app por el código fuente",
|
||||||
"removeOnExternalUninstall": "Auto eliminar apps desinstaladas externamente",
|
"removeOnExternalUninstall": "Auto eliminar apps desinstaladas externamente",
|
||||||
"pickHighestVersionCode": "Auto selección versión superior del código APK",
|
"pickHighestVersionCode": "Auto selección de versión superior del paquete APK",
|
||||||
"checkUpdateOnDetailPage": "Comprobar actualizaciones al abrir detalles de la app",
|
"checkUpdateOnDetailPage": "Comprobar actualizaciones al abrir detalles de la app",
|
||||||
"disablePageTransitions": "Deshabilitar animaciones de transición",
|
"disablePageTransitions": "Deshabilitar animaciones de transición",
|
||||||
"reversePageTransitions": "Invertir animaciones de transición",
|
"reversePageTransitions": "Invertir animaciones de transición",
|
||||||
"minStarCount": "Número Mínimo de Estrellas",
|
"minStarCount": "Número Mínimo de Estrellas",
|
||||||
"addInfoBelow": "Añadir esta información debajo.",
|
"addInfoBelow": "Añadir esta información debajo.",
|
||||||
"addInfoInSettings": "Puede añadir esta información en Ajustes.",
|
"addInfoInSettings": "Puede añadir esta información en Ajustes.",
|
||||||
"githubSourceNote": "La limitación de velocidad de GitHub puede evitarse con una clave API.",
|
"githubSourceNote": "La limitación de velocidad de GitHub puede evitarse con un 'token de acceso personal'.",
|
||||||
"gitlabSourceNote": "La extracción de APK de GitLab podría no funcionar sin una clave API.",
|
"gitlabSourceNote": "La extracción de APK de GitLab podría no funcionar sin un 'token de acceso personal'.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Ordenar sólo por el último segmento del enlace",
|
||||||
"filterReleaseNotesByRegEx": "Filtrar por notas de versión (release notes)",
|
"filterReleaseNotesByRegEx": "Filtrar por notas de versión (release notes)",
|
||||||
"customLinkFilterRegex": "Filtro personalizado de Enlace APK (por defecto '.apk$')",
|
"customLinkFilterRegex": "Filtro personalizado de enlace APK (por defecto '.apk$')",
|
||||||
"appsPossiblyUpdated": "Actualización de Apps intentada",
|
"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",
|
"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 {}.",
|
"xWasPossiblyUpdatedToY": "{} podría estar actualizada a {}.",
|
||||||
"enableBackgroundUpdates": "Habilitar actualizaciones en segundo plano",
|
"enableBackgroundUpdates": "Habilitar actualizaciones en segundo plano",
|
||||||
@ -246,21 +245,21 @@
|
|||||||
"backgroundUpdateLimitsExplanation": "El éxito de las instalaciones en segundo plano solo se puede comprobar con Obtainium abierto.",
|
"backgroundUpdateLimitsExplanation": "El éxito de las instalaciones en segundo plano solo se puede comprobar con Obtainium abierto.",
|
||||||
"verifyLatestTag": "Comprobar la etiqueta 'Latest'",
|
"verifyLatestTag": "Comprobar la etiqueta 'Latest'",
|
||||||
"intermediateLinkRegex": "Filtrar por enlace 'intermedio' para visitar primero",
|
"intermediateLinkRegex": "Filtrar por enlace 'intermedio' para visitar primero",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Filtrar enlaces por texto del enlace",
|
||||||
"intermediateLinkNotFound": "Enlace intermedio no encontrado",
|
"intermediateLinkNotFound": "Enlace intermedio no encontrado",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Enlace intermedio",
|
||||||
"exemptFromBackgroundUpdates": "Exenta de actualizciones en segundo plano (si están habilitadas)",
|
"exemptFromBackgroundUpdates": "Exenta de actualizciones en segundo plano (si están habilitadas)",
|
||||||
"bgUpdatesOnWiFiOnly": "Deshabilitar las actualizaciones en segundo plano sin WiFi",
|
"bgUpdatesOnWiFiOnly": "Deshabilitar las actualizaciones en segundo plano sin WiFi",
|
||||||
"autoSelectHighestVersionCode": "Auto Selección de la versionCode APK superior",
|
"autoSelectHighestVersionCode": "Auto selección del paquete APK con versión más reciente",
|
||||||
"versionExtractionRegEx": "Versión de extracción regex",
|
"versionExtractionRegEx": "Versión de extracción regex",
|
||||||
"matchGroupToUse": "Grupo a usar para versión de extracción regex",
|
"matchGroupToUse": "Grupo a usar para versión de extracción regex",
|
||||||
"highlightTouchTargets": "Resaltar objetivos menos obvios",
|
"highlightTouchTargets": "Resaltar objetivos menos obvios",
|
||||||
"pickExportDir": "Directorio para Exportar",
|
"pickExportDir": "Directorio para exportar",
|
||||||
"autoExportOnChanges": "Auto Exportar cuando haya cambios",
|
"autoExportOnChanges": "Auto exportar cuando haya cambios",
|
||||||
"includeSettings": "Incluir ajustes",
|
"includeSettings": "Incluir ajustes",
|
||||||
"filterVersionsByRegEx": "Filtrar por Versiones",
|
"filterVersionsByRegEx": "Filtrar por versiones",
|
||||||
"trySelectingSuggestedVersionCode": "Pruebe seleccionando la versionCode APK sugerida",
|
"trySelectingSuggestedVersionCode": "Pruebe seleccionando la versión del paquete APK sugerida",
|
||||||
"dontSortReleasesList": "Mantener el order de publicación desde API",
|
"dontSortReleasesList": "Mantener el order de publicación de la fuente original",
|
||||||
"reverseSort": "Orden inverso",
|
"reverseSort": "Orden inverso",
|
||||||
"takeFirstLink": "Usar primer enlace",
|
"takeFirstLink": "Usar primer enlace",
|
||||||
"skipSort": "Omitir orden",
|
"skipSort": "Omitir orden",
|
||||||
@ -284,9 +283,24 @@
|
|||||||
"parallelDownloads": "Permitir descargas paralelas",
|
"parallelDownloads": "Permitir descargas paralelas",
|
||||||
"installMethod": "Método de instalación",
|
"installMethod": "Método de instalación",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"shizuku": "Shizuku",
|
"root": "Raíz",
|
||||||
"root": "Root",
|
"shizukuBinderNotFound": "Shizuku no funciona",
|
||||||
"shizukuBinderNotFound": "Shizuku no está operativo",
|
"useSystemFont": "Usar la fuente de impresión del sistema",
|
||||||
|
"systemFontError": "Error al cargar la fuente de impresión del sistema: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Usar la versión de la aplicación como versión detectada por el sistema operativo",
|
||||||
|
"requestHeader": "Encabezado de solicitud",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Usar la última carga de recursos como fecha de lanzamiento",
|
||||||
|
"defaultPseudoVersioningMethod": "Método de pseudoversionado predeterminado",
|
||||||
|
"partialAPKHash": "Hash de APK parcial",
|
||||||
|
"APKLinkHash": "Hash de enlace APK",
|
||||||
|
"directAPKLink": "Enlace APK directo",
|
||||||
|
"pseudoVersionInUse": "Se está utilizando una pseudoversión",
|
||||||
|
"installed": "Instalado",
|
||||||
|
"latest": "Versión más reciente",
|
||||||
|
"invertRegEx": "Invertir expresión regular",
|
||||||
|
"note": "Nota",
|
||||||
|
"selfHostedNote": "El desplegable \"{}\" puede utilizarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.",
|
||||||
|
"badDownload": "No se ha podido analizar el APK (incompatible o descarga parcial)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "¿Eliminar Aplicación?",
|
"one": "¿Eliminar Aplicación?",
|
||||||
"other": "¿Eliminar Aplicaciones?"
|
"other": "¿Eliminar Aplicaciones?"
|
||||||
@ -308,8 +322,8 @@
|
|||||||
"other": "{} Aplicaciones"
|
"other": "{} Aplicaciones"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"one": "{} URL",
|
"uno": "{} URL",
|
||||||
"other": "{} URLs"
|
"otro": "{} URL"
|
||||||
},
|
},
|
||||||
"minute": {
|
"minute": {
|
||||||
"one": "{} minuto",
|
"one": "{} minuto",
|
||||||
|
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "پیش رفتن: {}%",
|
"percentProgress": "پیش رفتن: {}%",
|
||||||
"pleaseWait": "لطفا صبر کنید",
|
"pleaseWait": "لطفا صبر کنید",
|
||||||
"updateAvailable": "بروزرسانی در دسترس",
|
"updateAvailable": "بروزرسانی در دسترس",
|
||||||
"estimateInBracketsShort": "(تخمین)",
|
|
||||||
"notInstalled": "نصب نشده",
|
"notInstalled": "نصب نشده",
|
||||||
"estimateInBrackets": "(تخمین زدن)",
|
"pseudoVersion": "نسخه شبه",
|
||||||
"selectAll": "انتخاب همه",
|
"selectAll": "انتخاب همه",
|
||||||
"deselectX": "لغو انتخاب {}",
|
"deselectX": "لغو انتخاب {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} از Obtainium حذف میشود اما روی دستگاه نصب میماند.",
|
"xWillBeRemovedButRemainInstalled": "{} از Obtainium حذف میشود اما روی دستگاه نصب میماند.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "برداشتن پین از بالا",
|
"unpinFromTop": "برداشتن پین از بالا",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "وضعیت نصب برنامههای انتخابی بازنشانی شود؟",
|
"resetInstallStatusForSelectedAppsQuestion": "وضعیت نصب برنامههای انتخابی بازنشانی شود؟",
|
||||||
"installStatusOfXWillBeResetExplanation": "وضعیت نصب برنامههای انتخابشده بازنشانی میشود.\n\nاگر نسخه برنامه نشاندادهشده در Obtainium به دلیل بهروزرسانیهای ناموفق یا مشکلات دیگر نادرست باشد، میتواند کمک کند.",
|
"installStatusOfXWillBeResetExplanation": "وضعیت نصب برنامههای انتخابشده بازنشانی میشود.\n\nاگر نسخه برنامه نشاندادهشده در Obtainium به دلیل بهروزرسانیهای ناموفق یا مشکلات دیگر نادرست باشد، میتواند کمک کند.",
|
||||||
|
"customLinkMessage": "این پیوندها بر روی دستگاه هایی با Obtainium نصب شده کار می کنند",
|
||||||
|
"shareAppConfigLinks": "اشتراک گذاری پیکربندی برنامه به عنوان پیوند HTML",
|
||||||
"shareSelectedAppURLs": "اشتراک گذاری آدرس اینترنتی برنامه های انتخاب شده",
|
"shareSelectedAppURLs": "اشتراک گذاری آدرس اینترنتی برنامه های انتخاب شده",
|
||||||
"resetInstallStatus": "بازنشانی وضعیت نصب",
|
"resetInstallStatus": "بازنشانی وضعیت نصب",
|
||||||
"more": "بیشتر",
|
"more": "بیشتر",
|
||||||
@ -85,22 +86,22 @@
|
|||||||
"author": "سازنده",
|
"author": "سازنده",
|
||||||
"upToDateApps": "برنامه های به روز",
|
"upToDateApps": "برنامه های به روز",
|
||||||
"nonInstalledApps": "برنامه های نصب نشده",
|
"nonInstalledApps": "برنامه های نصب نشده",
|
||||||
"importExport": "وادر کردن/صادر کردن",
|
"importExport": "درون ریزی/برون ریزی",
|
||||||
"settings": "تنظیمات",
|
"settings": "تنظیمات",
|
||||||
"exportedTo": "صادر کردن به{}",
|
"exportedTo": "برون ریزی به{}",
|
||||||
"obtainiumExport": "صادرکردن Obtainium",
|
"obtainiumExport": "صادرکردن Obtainium",
|
||||||
"invalidInput": "ورودی نامعتبر",
|
"invalidInput": "ورودی نامعتبر",
|
||||||
"importedX": "وارد شده {}",
|
"importedX": "وارد شده {}",
|
||||||
"obtainiumImport": "واردکردن Obtainium",
|
"obtainiumImport": "واردکردن Obtainium",
|
||||||
"importFromURLList": "وارد کردن از فهرست آدرس اینترنتی",
|
"importFromURLList": "درون ریزی از فهرست آدرس اینترنتی",
|
||||||
"searchQuery": "جستجوی سوال",
|
"searchQuery": "جستجوی سوال",
|
||||||
"appURLList": "فهرست آدرس اینترنتی برنامه",
|
"appURLList": "فهرست آدرس اینترنتی برنامه",
|
||||||
"line": "خط",
|
"line": "خط",
|
||||||
"searchX": "جستجو {}",
|
"searchX": "جستجو {}",
|
||||||
"noResults": "نتیجه ای پیدا نشد",
|
"noResults": "نتیجه ای پیدا نشد",
|
||||||
"importX": "وارد کردن {}",
|
"importX": "درون ریزی {}",
|
||||||
"importedAppsIdDisclaimer": "ممکن است برنامههای وارد شده به اشتباه بهعنوان \"نصب نشده\" نشان داده شوند.\nبرای رفع این مشکل، آنها را دوباره از طریق Obtainium نصب کنید.\nاین نباید روی دادههای برنامه تأثیر بگذارد.\n\nفقط بر روی آدرس اینترنتی و روشهای وارد کردن شخص ثالث تأثیر میگذارد.",
|
"importedAppsIdDisclaimer": "ممکن است برنامههای وارد شده به اشتباه بهعنوان \"نصب نشده\" نشان داده شوند.\nبرای رفع این مشکل، آنها را دوباره از طریق Obtainium نصب کنید.\nاین نباید روی دادههای برنامه تأثیر بگذارد.\n\nفقط بر روی آدرس اینترنتی و روشهای درون ریزی شخص ثالث تأثیر میگذارد.",
|
||||||
"importErrors": "خطاهای وارد کردن",
|
"importErrors": "خطاهای درون ریزی",
|
||||||
"importedXOfYApps": "{} از {} برنامه وارد شد.",
|
"importedXOfYApps": "{} از {} برنامه وارد شد.",
|
||||||
"followingURLsHadErrors": "آدرس های اینترنتی زیر دارای خطا بودند:",
|
"followingURLsHadErrors": "آدرس های اینترنتی زیر دارای خطا بودند:",
|
||||||
"selectURL": "آدرس اینترنتی انتخاب شده",
|
"selectURL": "آدرس اینترنتی انتخاب شده",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "تاریک",
|
"dark": "تاریک",
|
||||||
"light": "روشن",
|
"light": "روشن",
|
||||||
"followSystem": "هماهنگ با سیستم",
|
"followSystem": "هماهنگ با سیستم",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "استفاده از تم تیره سیاه خالص",
|
"useBlackTheme": "استفاده از تم تیره سیاه خالص",
|
||||||
"appSortBy": "مرتب سازی برنامه بر اساس",
|
"appSortBy": "مرتب سازی برنامه بر اساس",
|
||||||
"authorName": "سازنده/اسم",
|
"authorName": "سازنده/اسم",
|
||||||
@ -133,7 +132,7 @@
|
|||||||
"close": "بستن",
|
"close": "بستن",
|
||||||
"share": "اشتراک گذاری",
|
"share": "اشتراک گذاری",
|
||||||
"appNotFound": "برنامه پیدا نشد",
|
"appNotFound": "برنامه پیدا نشد",
|
||||||
"obtainiumExportHyphenatedLowercase": "صادر کردن-obtainium",
|
"obtainiumExportHyphenatedLowercase": "برون ریزی-obtainium",
|
||||||
"pickAnAPK": "یک APK انتخاب کنید",
|
"pickAnAPK": "یک APK انتخاب کنید",
|
||||||
"appHasMoreThanOnePackage": "{} بیش از یک بسته دارد:",
|
"appHasMoreThanOnePackage": "{} بیش از یک بسته دارد:",
|
||||||
"deviceSupportsXArch": "دستگاه شما از معماری پردازنده {} پشتیبانی میکند",
|
"deviceSupportsXArch": "دستگاه شما از معماری پردازنده {} پشتیبانی میکند",
|
||||||
@ -171,13 +170,12 @@
|
|||||||
"yesMarkUpdated": "بله، علامت گذاری به عنوان به روز شده",
|
"yesMarkUpdated": "بله، علامت گذاری به عنوان به روز شده",
|
||||||
"fdroid": "F-Droid Official",
|
"fdroid": "F-Droid Official",
|
||||||
"appIdOrName": "شناسه یا نام برنامه",
|
"appIdOrName": "شناسه یا نام برنامه",
|
||||||
"appId": "App ID",
|
"appId": "شناسه برنامه",
|
||||||
"appWithIdOrNameNotFound": "هیچ برنامه ای با آن شناسه یا نام یافت نشد",
|
"appWithIdOrNameNotFound": "هیچ برنامه ای با آن شناسه یا نام یافت نشد",
|
||||||
"reposHaveMultipleApps": "مخازن ممکن است شامل چندین برنامه باشد",
|
"reposHaveMultipleApps": "مخازن ممکن است شامل چندین برنامه باشد",
|
||||||
"fdroidThirdPartyRepo": "مخازن شخص ثالث F-Droid",
|
"fdroidThirdPartyRepo": "مخازن شخص ثالث F-Droid",
|
||||||
"steam": "Steam",
|
"steamMobile": "استیم موبایل",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "چت استیم",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "نصب",
|
"install": "نصب",
|
||||||
"markInstalled": "علامت گذاری به عنوان نصب شده",
|
"markInstalled": "علامت گذاری به عنوان نصب شده",
|
||||||
"update": "به روز رسانی",
|
"update": "به روز رسانی",
|
||||||
@ -210,7 +208,8 @@
|
|||||||
"releaseDateAsVersionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند، اما تاریخ انتشار در دسترس است.",
|
"releaseDateAsVersionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند، اما تاریخ انتشار در دسترس است.",
|
||||||
"changes": "تغییرات",
|
"changes": "تغییرات",
|
||||||
"releaseDate": "تاریخ انتشار",
|
"releaseDate": "تاریخ انتشار",
|
||||||
"importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)",
|
"importFromURLsInFile": "درون ریزی از آدرس های اینترنتی موجود در فایل (مانند OPML)",
|
||||||
|
"versionDetectionExplanation": "تطبیق رشته نسخه با نسخه شناسایی شده از سیستم عامل",
|
||||||
"versionDetection": "تشخیص نسخه",
|
"versionDetection": "تشخیص نسخه",
|
||||||
"standardVersionDetection": "تشخیص نسخه استاندارد",
|
"standardVersionDetection": "تشخیص نسخه استاندارد",
|
||||||
"groupByCategory": "گروه بر اساس دسته",
|
"groupByCategory": "گروه بر اساس دسته",
|
||||||
@ -235,7 +234,7 @@
|
|||||||
"addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.",
|
"addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.",
|
||||||
"githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.",
|
"githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.",
|
||||||
"gitlabSourceNote": "استخراج APK GitLab ممکن است بدون کلید API کار نکند.",
|
"gitlabSourceNote": "استخراج APK GitLab ممکن است بدون کلید API کار نکند.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "فقط بر اساس آخرین بخش پیوند مرتب کنید",
|
||||||
"filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید",
|
"filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید",
|
||||||
"customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیشفرض '.apk$')",
|
"customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیشفرض '.apk$')",
|
||||||
"appsPossiblyUpdated": "بهروزرسانی برنامه انجام شد",
|
"appsPossiblyUpdated": "بهروزرسانی برنامه انجام شد",
|
||||||
@ -245,25 +244,25 @@
|
|||||||
"backgroundUpdateReqsExplanation": "به روز رسانی پس زمینه ممکن است برای همه برنامه ها امکان پذیر نباشد.",
|
"backgroundUpdateReqsExplanation": "به روز رسانی پس زمینه ممکن است برای همه برنامه ها امکان پذیر نباشد.",
|
||||||
"backgroundUpdateLimitsExplanation": "موفقیت نصب پسزمینه تنها زمانی مشخص میشود که Obtainium باز شود.",
|
"backgroundUpdateLimitsExplanation": "موفقیت نصب پسزمینه تنها زمانی مشخص میشود که Obtainium باز شود.",
|
||||||
"verifyLatestTag": "برچسب \"آخرین\" را تأیید کنید",
|
"verifyLatestTag": "برچسب \"آخرین\" را تأیید کنید",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "برای بازدید از پیوند «میانگین» فیلتر کنید",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "لینک ها را بر اساس متن پیوند فیلتر کنید",
|
||||||
"intermediateLinkNotFound": "لینک میانی پیدا نشد",
|
"intermediateLinkNotFound": "لینک میانی پیدا نشد",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "پیوند میانی",
|
||||||
"exemptFromBackgroundUpdates": "معاف از بهروزرسانیهای پسزمینه (در صورت فعال بودن)",
|
"exemptFromBackgroundUpdates": "معاف از بهروزرسانیهای پسزمینه (در صورت فعال بودن)",
|
||||||
"bgUpdatesOnWiFiOnly": "بهروزرسانیهای پسزمینه را در صورت عدم اتصال به WiFi غیرفعال کنید",
|
"bgUpdatesOnWiFiOnly": "بهروزرسانیهای پسزمینه را در صورت عدم اتصال به WiFi غیرفعال کنید",
|
||||||
"autoSelectHighestVersionCode": "انتخاب خودکار بالاترین نسخه کد APK",
|
"autoSelectHighestVersionCode": "انتخاب خودکار بالاترین نسخه کد APK",
|
||||||
"versionExtractionRegEx": "نسخه استخراج RegEx",
|
"versionExtractionRegEx": "نسخه استخراج RegEx",
|
||||||
"matchGroupToUse": "گروه مورد استفاده را مطابقت دهید",
|
"matchGroupToUse": "گروه مورد استفاده را مطابقت دهید",
|
||||||
"highlightTouchTargets": "اهداف لمسی کمتر واضح را برجسته کنید",
|
"highlightTouchTargets": "اهداف لمسی کمتر واضح را برجسته کنید",
|
||||||
"pickExportDir": "فهرست صادرات را انتخاب کنید",
|
"pickExportDir": "فهرست برون ریزی را انتخاب کنید",
|
||||||
"autoExportOnChanges": "صادرات خودکار تغییرات",
|
"autoExportOnChanges": "برون ریزی خودکار تغییرات",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "شامل تنظیمات",
|
||||||
"filterVersionsByRegEx": "فیلتر کردن نسخه ها با RegEx",
|
"filterVersionsByRegEx": "فیلتر کردن نسخه ها با RegEx",
|
||||||
"trySelectingSuggestedVersionCode": "نسخه پیشنهادی APK نسخه کد را انتخاب کنید",
|
"trySelectingSuggestedVersionCode": "نسخه پیشنهادی APK نسخه کد را انتخاب کنید",
|
||||||
"dontSortReleasesList": "حفظ سفارش انتشار از API",
|
"dontSortReleasesList": "حفظ سفارش انتشار از API",
|
||||||
"reverseSort": "مرتب سازی معکوس",
|
"reverseSort": "مرتب سازی معکوس",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "لینک اول را بگیرید",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "از مرتب سازی صرف نظر کنید",
|
||||||
"debugMenu": "منوی اشکال زدایی",
|
"debugMenu": "منوی اشکال زدایی",
|
||||||
"bgTaskStarted": "کار پس زمینه شروع شد - لاگ های مربوط را بررسی کنید.",
|
"bgTaskStarted": "کار پس زمینه شروع شد - لاگ های مربوط را بررسی کنید.",
|
||||||
"runBgCheckNow": "اکنون بهروزرسانی پسزمینه را بررسی کنید",
|
"runBgCheckNow": "اکنون بهروزرسانی پسزمینه را بررسی کنید",
|
||||||
@ -281,12 +280,27 @@
|
|||||||
"onlyCheckInstalledOrTrackOnlyApps": "فقط برنامه های نصب شده و فقط ردیابی را برای به روز رسانی بررسی کنید",
|
"onlyCheckInstalledOrTrackOnlyApps": "فقط برنامه های نصب شده و فقط ردیابی را برای به روز رسانی بررسی کنید",
|
||||||
"supportFixedAPKURL": "پشتیبانی از URL های APK ثابت",
|
"supportFixedAPKURL": "پشتیبانی از URL های APK ثابت",
|
||||||
"selectX": "انتخاب کنید {}",
|
"selectX": "انتخاب کنید {}",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "اجازه دانلود موازی",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "روش نصب",
|
||||||
"normal": "Normal",
|
"normal": "طبیعی",
|
||||||
"shizuku": "Shizuku",
|
"root": "ریشه",
|
||||||
"root": "Root",
|
"shizukuBinderNotFound": "Shizuku در حال اجرا نیست",
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"useSystemFont": "استفاده از فونت سیستم",
|
||||||
|
"systemFontError": "خطا در بارگیری فونت سیستم: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "استفاده کد نسخه برنامه به جای نسخه شناسایی شده توسط سیستم عامل استفاده کنید",
|
||||||
|
"requestHeader": "درخواست سطر بالایی",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "استفاده از آخرین بارگذاری دارایی به عنوان تاریخ انتشار",
|
||||||
|
"defaultPseudoVersioningMethod": "روش پیش فرض شبه نسخه",
|
||||||
|
"partialAPKHash": "هش جزئی APK",
|
||||||
|
"APKLinkHash": "هش پیوند APK",
|
||||||
|
"directAPKLink": "لینک مستقیم APK",
|
||||||
|
"pseudoVersionInUse": "یک نسخه شبه در حال استفاده است",
|
||||||
|
"installed": "نصب شده است",
|
||||||
|
"latest": "آخرین",
|
||||||
|
"invertRegEx": "معکوس کردن عبارت منظم",
|
||||||
|
"note": "Note",
|
||||||
|
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
|
||||||
|
"badDownload": "The APK could not be parsed (incompatible or partial download)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "برنامه حذف شود؟",
|
"one": "برنامه حذف شود؟",
|
||||||
"other": "برنامه ها حذف شوند؟"
|
"other": "برنامه ها حذف شوند؟"
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"placeholder": "Espace réservé",
|
"placeholder": "Espace réservé",
|
||||||
"someErrors": "Des erreurs se sont produites",
|
"someErrors": "Des erreurs se sont produites",
|
||||||
"unexpectedError": "Erreur inattendue",
|
"unexpectedError": "Erreur inattendue",
|
||||||
"ok": "Okay",
|
"ok": "D'accord",
|
||||||
"and": "et",
|
"and": "et",
|
||||||
"githubPATLabel": "Jeton d'Accès Personnel GitHub (Augmente la limite de débit)",
|
"githubPATLabel": "Jeton d'Accès Personnel GitHub (Augmente la limite de débit)",
|
||||||
"includePrereleases": "Inclure les avant-premières",
|
"includePrereleases": "Inclure les avant-premières",
|
||||||
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Progrès: {}%",
|
"percentProgress": "Progrès: {}%",
|
||||||
"pleaseWait": "Veuillez patienter",
|
"pleaseWait": "Veuillez patienter",
|
||||||
"updateAvailable": "Mise à jour disponible",
|
"updateAvailable": "Mise à jour disponible",
|
||||||
"estimateInBracketsShort": "(Est.)",
|
|
||||||
"notInstalled": "Pas installé",
|
"notInstalled": "Pas installé",
|
||||||
"estimateInBrackets": "(Estimation)",
|
"pseudoVersion": "pseudo-version",
|
||||||
"selectAll": "Tout sélectionner",
|
"selectAll": "Tout sélectionner",
|
||||||
"deselectX": "Déselectionner {}",
|
"deselectX": "Déselectionner {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} sera supprimé d'Obtainium mais restera installé sur l'appareil.",
|
"xWillBeRemovedButRemainInstalled": "{} sera supprimé d'Obtainium mais restera installé sur l'appareil.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Détacher du haut",
|
"unpinFromTop": "Détacher du haut",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Réinitialiser l'état d'installation des applications sélectionnées ?",
|
"resetInstallStatusForSelectedAppsQuestion": "Réinitialiser l'état d'installation des applications sélectionnées ?",
|
||||||
"installStatusOfXWillBeResetExplanation": "L'état d'installation de toutes les applications sélectionnées sera réinitialisé.\n\nCela peut aider lorsque la version de l'application affichée dans Obtainium est incorrecte en raison d'échecs de mises à jour ou d'autres problèmes.",
|
"installStatusOfXWillBeResetExplanation": "L'état d'installation de toutes les applications sélectionnées sera réinitialisé.\n\nCela peut aider lorsque la version de l'application affichée dans Obtainium est incorrecte en raison d'échecs de mises à jour ou d'autres problèmes.",
|
||||||
|
"customLinkMessage": "Ces liens fonctionnent sur les appareils sur lesquels Obtenirium est installé",
|
||||||
|
"shareAppConfigLinks": "Partager la configuration de l'application sous forme de lien HTML",
|
||||||
"shareSelectedAppURLs": "Partager les URL d'application sélectionnées",
|
"shareSelectedAppURLs": "Partager les URL d'application sélectionnées",
|
||||||
"resetInstallStatus": "Réinitialiser le statut d'installation",
|
"resetInstallStatus": "Réinitialiser le statut d'installation",
|
||||||
"more": "Plus",
|
"more": "Plus",
|
||||||
@ -110,9 +111,7 @@
|
|||||||
"dark": "Sombre",
|
"dark": "Sombre",
|
||||||
"light": "Clair",
|
"light": "Clair",
|
||||||
"followSystem": "Suivre le système",
|
"followSystem": "Suivre le système",
|
||||||
"obtainium": "Obtainium",
|
"useBlackTheme": "Utilisez le thème noir pur et sombre",
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Use pure black dark theme",
|
|
||||||
"appSortBy": "Applications triées par",
|
"appSortBy": "Applications triées par",
|
||||||
"authorName": "Auteur/Nom",
|
"authorName": "Auteur/Nom",
|
||||||
"nameAuthor": "Nom/Auteur",
|
"nameAuthor": "Nom/Auteur",
|
||||||
@ -133,7 +132,7 @@
|
|||||||
"close": "Fermer",
|
"close": "Fermer",
|
||||||
"share": "Partager",
|
"share": "Partager",
|
||||||
"appNotFound": "Application introuvable",
|
"appNotFound": "Application introuvable",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"obtainiumExportHyphenatedLowercase": "exportation d'obtainium",
|
||||||
"pickAnAPK": "Choisissez un APK",
|
"pickAnAPK": "Choisissez un APK",
|
||||||
"appHasMoreThanOnePackage": "{} a plus d'un paquet :",
|
"appHasMoreThanOnePackage": "{} a plus d'un paquet :",
|
||||||
"deviceSupportsXArch": "Votre appareil prend en charge l'architecture de processeur {}.",
|
"deviceSupportsXArch": "Votre appareil prend en charge l'architecture de processeur {}.",
|
||||||
@ -169,15 +168,14 @@
|
|||||||
"lastUpdateCheckX": "Vérification de la dernière mise à jour : {}",
|
"lastUpdateCheckX": "Vérification de la dernière mise à jour : {}",
|
||||||
"remove": "Retirer",
|
"remove": "Retirer",
|
||||||
"yesMarkUpdated": "Oui, marquer comme mis à jour",
|
"yesMarkUpdated": "Oui, marquer comme mis à jour",
|
||||||
"fdroid": "F-Droid Official",
|
"fdroid": "F-Droïde Officiel",
|
||||||
"appIdOrName": "ID ou nom de l'application",
|
"appIdOrName": "ID ou nom de l'application",
|
||||||
"appId": "ID de l'application",
|
"appId": "ID de l'application",
|
||||||
"appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom",
|
"appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom",
|
||||||
"reposHaveMultipleApps": "Les dépôts peuvent contenir plusieurs applications",
|
"reposHaveMultipleApps": "Les dépôts peuvent contenir plusieurs applications",
|
||||||
"fdroidThirdPartyRepo": "Dépôt tiers F-Droid",
|
"fdroidThirdPartyRepo": "Dépôt tiers F-Droid",
|
||||||
"steam": "Steam",
|
"steamMobile": "Vapeur Mobile",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "Chat sur Steam",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "Installer",
|
"install": "Installer",
|
||||||
"markInstalled": "Marquer installée",
|
"markInstalled": "Marquer installée",
|
||||||
"update": "Mettre à jour",
|
"update": "Mettre à jour",
|
||||||
@ -192,14 +190,14 @@
|
|||||||
"categorize": "Catégoriser",
|
"categorize": "Catégoriser",
|
||||||
"categories": "Catégories",
|
"categories": "Catégories",
|
||||||
"category": "Catégorie",
|
"category": "Catégorie",
|
||||||
"noCategory": "No Category",
|
"noCategory": "Aucune catégorie",
|
||||||
"noCategories": "Aucune catégorie",
|
"noCategories": "Aucune catégorie",
|
||||||
"deleteCategoriesQuestion": "Supprimer les catégories ?",
|
"deleteCategoriesQuestion": "Supprimer les catégories ?",
|
||||||
"categoryDeleteWarning": "Toutes les applications dans les catégories supprimées seront définies sur non catégorisées.",
|
"categoryDeleteWarning": "Toutes les applications dans les catégories supprimées seront définies sur non catégorisées.",
|
||||||
"addCategory": "Ajouter une catégorie",
|
"addCategory": "Ajouter une catégorie",
|
||||||
"label": "Étiquette",
|
"label": "Étiquette",
|
||||||
"language": "Langue",
|
"language": "Langue",
|
||||||
"copiedToClipboard": "Copied to Clipboard",
|
"copiedToClipboard": "Copié dans le presse-papier",
|
||||||
"storagePermissionDenied": "Autorisation de stockage refusée",
|
"storagePermissionDenied": "Autorisation de stockage refusée",
|
||||||
"selectedCategorizeWarning": "Cela remplacera tous les paramètres de catégorie existants pour les applications sélectionnées.",
|
"selectedCategorizeWarning": "Cela remplacera tous les paramètres de catégorie existants pour les applications sélectionnées.",
|
||||||
"filterAPKsByRegEx": "Filtrer les APK par expression régulière",
|
"filterAPKsByRegEx": "Filtrer les APK par expression régulière",
|
||||||
@ -211,82 +209,98 @@
|
|||||||
"changes": "Changements",
|
"changes": "Changements",
|
||||||
"releaseDate": "Date de sortie",
|
"releaseDate": "Date de sortie",
|
||||||
"importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)",
|
"importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)",
|
||||||
|
"versionDetectionExplanation": "Réconcilier la chaîne de version avec la version détectée à partir du système d'exploitation",
|
||||||
"versionDetection": "Détection des versions",
|
"versionDetection": "Détection des versions",
|
||||||
"standardVersionDetection": "Détection de version standard",
|
"standardVersionDetection": "Détection de version standard",
|
||||||
"groupByCategory": "Group by Category",
|
"groupByCategory": "Regrouper par catégorie",
|
||||||
"autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible",
|
"autoApkFilterByArch": "Essayez de filtrer les APK par architecture CPU si possible",
|
||||||
"overrideSource": "Override Source",
|
"overrideSource": "Remplacer la source",
|
||||||
"dontShowAgain": "Don't show this again",
|
"dontShowAgain": "Ne montre plus ça",
|
||||||
"dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning",
|
"dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning",
|
||||||
"dontShowAPKOriginWarnings": "Don't show APK origin warnings",
|
"dontShowAPKOriginWarnings": "Ne pas afficher les avertissements sur l'origine de l'APK",
|
||||||
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
"moveNonInstalledAppsToBottom": "Déplacer les applications non installées vers le bas de la vue Applications",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)",
|
"gitlabPATLabel": "Jeton d'accès personnel GitLab\\n (permet la recherche et une meilleure découverte d'APK)",
|
||||||
"about": "About",
|
"about": "À propos de",
|
||||||
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
||||||
"checkOnStart": "Check for updates on startup",
|
"checkOnStart": "Vérifier les mises à jour au démarrage",
|
||||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
"tryInferAppIdFromCode": "Essayez de déduire l'ID de l'application à partir du code source",
|
||||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
"removeOnExternalUninstall": "Supprimer automatiquement les applications désinstallées en externe",
|
||||||
"pickHighestVersionCode": "Auto-select highest version code APK",
|
"pickHighestVersionCode": "Sélectionner automatiquement le code APK de la version la plus élevée",
|
||||||
"checkUpdateOnDetailPage": "Check for updates on opening an App detail page",
|
"checkUpdateOnDetailPage": "Vérifier les mises à jour lors de l'ouverture d'une page de détails d'application",
|
||||||
"disablePageTransitions": "Disable page transition animations",
|
"disablePageTransitions": "Désactiver les animations de transition de page",
|
||||||
"reversePageTransitions": "Reverse page transition animations",
|
"reversePageTransitions": "Animations de transition de page inversée",
|
||||||
"minStarCount": "Minimum Star Count",
|
"minStarCount": "Nombre minimum d'étoiles",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "Ajoutez ces informations ci-dessous.",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Ajoutez ces informations dans les paramètres.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "La limitation du débit GitHub peut être évitée à l'aide d'une clé API.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "L'extraction d'APK GitLab peut ne pas fonctionner sans clé API.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Trier uniquement sur le dernier segment du lien",
|
||||||
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
"filterReleaseNotesByRegEx": "Filtrer les notes de version par expression régulière",
|
||||||
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
"customLinkFilterRegex": "Filtre de lien APK personnalisé par expression régulière (par défaut '.apk$')",
|
||||||
"appsPossiblyUpdated": "App Updates Attempted",
|
"appsPossiblyUpdated": "Tentative de mise à jour de l'application",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
|
"appsPossiblyUpdatedNotifDescription": "Avertit l'utilisateur que des mises à jour d'une ou plusieurs applications ont été potentiellement appliquées en arrière-plan",
|
||||||
"xWasPossiblyUpdatedToY": "{} may have been updated to {}.",
|
"xWasPossiblyUpdatedToY": "{} a peut-être été mis à jour vers {}.",
|
||||||
"enableBackgroundUpdates": "Enable background updates",
|
"enableBackgroundUpdates": "Activer les mises à jour en arrière-plan",
|
||||||
"backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.",
|
"backgroundUpdateReqsExplanation": "Les mises à jour en arrière-plan peuvent ne pas être possibles pour toutes les applications.",
|
||||||
"backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.",
|
"backgroundUpdateLimitsExplanation": "Le succès d'une installation en arrière-plan ne peut être déterminé qu'à l'ouverture d'Obetium.",
|
||||||
"verifyLatestTag": "Verify the 'latest' tag",
|
"verifyLatestTag": "Vérifiez la balise 'dernière'",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": " Filtrer un lien \" intermédiaire \" à visiter ",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Filtrer les liens par texte de lien",
|
||||||
"intermediateLinkNotFound": "Intermediate link not found",
|
"intermediateLinkNotFound": "Lien intermédiaire introuvable",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Lien intermédiaire",
|
||||||
"exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)",
|
"exemptFromBackgroundUpdates": "Exempt des mises à jour en arrière-plan (si activé)",
|
||||||
"bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
|
"bgUpdatesOnWiFiOnly": "Désactiver les mises à jour en arrière-plan lorsque vous n'êtes pas connecté au WiFi",
|
||||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
"autoSelectHighestVersionCode": "Sélection automatique de la version la plus élevéeCode APK",
|
||||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
"versionExtractionRegEx": "Version Extraction RegEx",
|
||||||
"matchGroupToUse": "Match Group to Use",
|
"matchGroupToUse": "Match Group to Use",
|
||||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
"highlightTouchTargets": "Mettez en évidence les cibles tactiles moins évidentes",
|
||||||
"pickExportDir": "Pick Export Directory",
|
"pickExportDir": "Choisir le répertoire d'exportation",
|
||||||
"autoExportOnChanges": "Auto-export on changes",
|
"autoExportOnChanges": "Exportation automatique sur modifications",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Inclure les paramètres",
|
||||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
"filterVersionsByRegEx": "Filtrer les versions par expression régulière",
|
||||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
"trySelectingSuggestedVersionCode": "Essayez de sélectionner la version suggéréeCode APK",
|
||||||
"dontSortReleasesList": "Retain release order from API",
|
"dontSortReleasesList": "Conserver la commande de version de l'API",
|
||||||
"reverseSort": "Reverse sorting",
|
"reverseSort": "Tri inversé",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Prendre le premier lien",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Sauter le tri",
|
||||||
"debugMenu": "Debug Menu",
|
"debugMenu": "Menu de débogage",
|
||||||
"bgTaskStarted": "Background task started - check logs.",
|
"bgTaskStarted": "Tâche en arrière-plan démarrée - vérifier les journaux.",
|
||||||
"runBgCheckNow": "Run Background Update Check Now",
|
"runBgCheckNow": "Exécuter la vérification de la mise à jour en arrière-plan maintenant",
|
||||||
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
"versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
|
||||||
"installing": "Installing",
|
"installing": "Installation",
|
||||||
"skipUpdateNotifications": "Skip update notifications",
|
"skipUpdateNotifications": "Ignorer les notifications de mise à jour",
|
||||||
"updatesAvailableNotifChannel": "Mises à jour disponibles",
|
"updatesAvailableNotifChannel": "Mises à jour disponibles",
|
||||||
"appsUpdatedNotifChannel": "Applications mises à jour",
|
"appsUpdatedNotifChannel": "Applications mises à jour",
|
||||||
"appsPossiblyUpdatedNotifChannel": "App Updates Attempted",
|
"appsPossiblyUpdatedNotifChannel": "Tentative de mise à jour de l'application",
|
||||||
"errorCheckingUpdatesNotifChannel": "Erreur lors de la vérification des mises à jour",
|
"errorCheckingUpdatesNotifChannel": "Erreur lors de la vérification des mises à jour",
|
||||||
"appsRemovedNotifChannel": "Applications supprimées",
|
"appsRemovedNotifChannel": "Applications supprimées",
|
||||||
"downloadingXNotifChannel": "Téléchargement {}",
|
"downloadingXNotifChannel": "Téléchargement {}",
|
||||||
"completeAppInstallationNotifChannel": "Installation complète de l'application",
|
"completeAppInstallationNotifChannel": "Installation complète de l'application",
|
||||||
"checkingForUpdatesNotifChannel": "Vérification des mises à jour",
|
"checkingForUpdatesNotifChannel": "Vérification des mises à jour",
|
||||||
"onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates",
|
"onlyCheckInstalledOrTrackOnlyApps": "Vérifiez uniquement les mises à jour des applications installées et de suivi uniquement",
|
||||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
"supportFixedAPKURL": "Prise en charge des URL APK fixes",
|
||||||
"selectX": "Select {}",
|
"selectX": "Sélectionner {}",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "Autoriser les téléchargements parallèles",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "Méthode d'installation",
|
||||||
"normal": "Normal",
|
"normal": "Normale",
|
||||||
"shizuku": "Shizuku",
|
"root": "Racine",
|
||||||
"root": "Root",
|
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"shizukuBinderNotFound": "Shizuku is not running",
|
||||||
|
"useSystemFont": "Utiliser la police système",
|
||||||
|
"systemFontError": "Erreur de chargement de la police système : {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Utiliser le code de version de l'application comme version détectée par le système d'exploitation",
|
||||||
|
"requestHeader": "En-tête de demande",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Utiliser le dernier téléchargement d'élément comme date de sortie",
|
||||||
|
"defaultPseudoVersioningMethod": "Méthode de pseudo-version par défaut",
|
||||||
|
"partialAPKHash": "Hash APK partiel",
|
||||||
|
"APKLinkHash": "Hash de lien APK",
|
||||||
|
"directAPKLink": "Lien APK direct",
|
||||||
|
"pseudoVersionInUse": "Une pseudo-version est utilisée",
|
||||||
|
"installed": "Installée",
|
||||||
|
"latest": "Dernier",
|
||||||
|
"invertRegEx": "Inverser l'expression régulière",
|
||||||
|
"note": "Note",
|
||||||
|
"selfHostedNote": "La liste déroulante \"{}\" peut être utilisée pour accéder aux instances auto-hébergées/personnalisées de n'importe quelle source.",
|
||||||
|
"badDownload": "L'APK n'a pas pu être analysé (téléchargement incompatible ou partiel)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Supprimer l'application ?",
|
"one": "Supprimer l'application ?",
|
||||||
"other": "Supprimer les applications ?"
|
"other": "Supprimer les applications ?"
|
||||||
@ -309,10 +323,10 @@
|
|||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"one": "{} URL",
|
"one": "{} URL",
|
||||||
"other": "{} URLs"
|
"other": "{} URL"
|
||||||
},
|
},
|
||||||
"minute": {
|
"minute": {
|
||||||
"one": "{} Minute",
|
"one": "{} Minutes",
|
||||||
"other": "{} Minutes"
|
"other": "{} Minutes"
|
||||||
},
|
},
|
||||||
"hour": {
|
"hour": {
|
||||||
@ -336,7 +350,7 @@
|
|||||||
"other": "{} et {} autres applications ont été mises à jour."
|
"other": "{} et {} autres applications ont été mises à jour."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
"one": "{} and 1 more app may have been updated.",
|
"une": "{} et 1 application supplémentaire ont peut-être été mises à jour.",
|
||||||
"other": "{} and {} more apps may have been updated."
|
"other": "{} et {} autres applications peuvent avoir été mises à jour."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
"wrongArgNum": "Rossz számú argumentumot adott meg",
|
"wrongArgNum": "Rossz számú argumentumot adott meg",
|
||||||
"xIsTrackOnly": "A(z) {} csak nyomonkövethető",
|
"xIsTrackOnly": "A(z) {} csak nyomonkövethető",
|
||||||
"source": "Forrás",
|
"source": "Forrás",
|
||||||
"app": "App",
|
"app": "Alkalmazás",
|
||||||
"appsFromSourceAreTrackOnly": "Az ebből a forrásból származó alkalmazások 'Csak nyomon követhetőek'.",
|
"appsFromSourceAreTrackOnly": "Az ebből a forrásból származó alkalmazások 'Csak nyomon követhetőek'.",
|
||||||
"youPickedTrackOnly": "A 'Csak követés' opciót választotta.",
|
"youPickedTrackOnly": "A 'Csak követés' opciót választotta.",
|
||||||
"trackOnlyAppDescription": "Az alkalmazás frissítéseit nyomon követi, de az Obtainium nem tudja letölteni vagy telepíteni.",
|
"trackOnlyAppDescription": "Az alkalmazás frissítéseit nyomon követi, de az Obtainium nem tudja letölteni vagy telepíteni.",
|
||||||
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Folyamat: {}%",
|
"percentProgress": "Folyamat: {}%",
|
||||||
"pleaseWait": "Kis türelmet",
|
"pleaseWait": "Kis türelmet",
|
||||||
"updateAvailable": "Frissítés érhető el",
|
"updateAvailable": "Frissítés érhető el",
|
||||||
"estimateInBracketsShort": "(Becsült)",
|
|
||||||
"notInstalled": "Nem telepített",
|
"notInstalled": "Nem telepített",
|
||||||
"estimateInBrackets": "(Becslés)",
|
"pseudoVersion": "ál-verzió",
|
||||||
"selectAll": "Mindet kiválaszt",
|
"selectAll": "Mindet kiválaszt",
|
||||||
"deselectX": "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.",
|
"xWillBeRemovedButRemainInstalled": "A(z) {} el lesz távolítva az Obtainiumból, de továbbra is telepítve marad az eszközön.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Eltávolít felülről",
|
"unpinFromTop": "Eltávolít felülről",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Visszaállítja a kiválasztott appok telepítési állapotát?",
|
"resetInstallStatusForSelectedAppsQuestion": "Visszaállítja a kiválasztott appok telepítési állapotát?",
|
||||||
"installStatusOfXWillBeResetExplanation": "A kiválasztott appok telepítési állapota visszaáll.\n\nEz akkor segíthet, ha az Obtainiumban megjelenített app verzió hibás, frissítések vagy egyéb problémák miatt.",
|
"installStatusOfXWillBeResetExplanation": "A kiválasztott appok telepítési állapota visszaáll.\n\nEz akkor segíthet, ha az Obtainiumban megjelenített app verzió hibás, frissítések vagy egyéb problémák miatt.",
|
||||||
|
"customLinkMessage": "Ezek a hivatkozások a telepített Obtainium-mal rendelkező eszközökön működnek",
|
||||||
|
"shareAppConfigLinks": "App konfiguráció megosztása HTML linkként",
|
||||||
"shareSelectedAppURLs": "Ossza meg a kiválasztott app URL címeit",
|
"shareSelectedAppURLs": "Ossza meg a kiválasztott app URL címeit",
|
||||||
"resetInstallStatus": "Telepítési állapot visszaállítása",
|
"resetInstallStatus": "Telepítési állapot visszaállítása",
|
||||||
"more": "További",
|
"more": "További",
|
||||||
@ -85,7 +86,7 @@
|
|||||||
"author": "Szerző",
|
"author": "Szerző",
|
||||||
"upToDateApps": "Naprakész appok",
|
"upToDateApps": "Naprakész appok",
|
||||||
"nonInstalledApps": "Nem telepített appok",
|
"nonInstalledApps": "Nem telepített appok",
|
||||||
"importExport": "Import/Export",
|
"importExport": "Import Export",
|
||||||
"settings": "Beállítások",
|
"settings": "Beállítások",
|
||||||
"exportedTo": "Exportálva ide {}",
|
"exportedTo": "Exportálva ide {}",
|
||||||
"obtainiumExport": "Obtainium Adat Exportálás",
|
"obtainiumExport": "Obtainium Adat Exportálás",
|
||||||
@ -98,7 +99,7 @@
|
|||||||
"line": "Sor",
|
"line": "Sor",
|
||||||
"searchX": "Keresés {}",
|
"searchX": "Keresés {}",
|
||||||
"noResults": "Nincs találat",
|
"noResults": "Nincs találat",
|
||||||
"importX": "Import {}",
|
"importX": "Importálás: {}",
|
||||||
"importedAppsIdDisclaimer": "Előfordulhat, hogy az importált appok helytelenül \"Nincs telepítve\" jelzéssel jelennek meg.\nA probléma megoldásához telepítse újra őket az Obtainiumon keresztül.\nEz nem érinti az alkalmazásadatokat.\n\nCsak az URL-ekre és a harmadik féltől származó importálási módszerekre vonatkozik..",
|
"importedAppsIdDisclaimer": "Előfordulhat, hogy az importált appok helytelenül \"Nincs telepítve\" jelzéssel jelennek meg.\nA probléma megoldásához telepítse újra őket az Obtainiumon keresztül.\nEz nem érinti az alkalmazásadatokat.\n\nCsak az URL-ekre és a harmadik féltől származó importálási módszerekre vonatkozik..",
|
||||||
"importErrors": "Importálási hibák",
|
"importErrors": "Importálási hibák",
|
||||||
"importedXOfYApps": "{}/{} app importálva.",
|
"importedXOfYApps": "{}/{} app importálva.",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Sötét",
|
"dark": "Sötét",
|
||||||
"light": "Világos",
|
"light": "Világos",
|
||||||
"followSystem": "Rendszer szerint",
|
"followSystem": "Rendszer szerint",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Használjon teljesen fekete sötét témát",
|
"useBlackTheme": "Használjon teljesen fekete sötét témát",
|
||||||
"appSortBy": "App rendezés...",
|
"appSortBy": "App rendezés...",
|
||||||
"authorName": "Szerző/Név",
|
"authorName": "Szerző/Név",
|
||||||
@ -169,14 +168,13 @@
|
|||||||
"lastUpdateCheckX": "Frissítés ellenőrizve: {}",
|
"lastUpdateCheckX": "Frissítés ellenőrizve: {}",
|
||||||
"remove": "Eltávolítás",
|
"remove": "Eltávolítás",
|
||||||
"yesMarkUpdated": "Igen, megjelölés frissítettként",
|
"yesMarkUpdated": "Igen, megjelölés frissítettként",
|
||||||
"fdroid": "F-Droid Official",
|
"fdroid": "F-Droid hivatalos",
|
||||||
"appIdOrName": "App ID vagy név",
|
"appIdOrName": "App ID vagy név",
|
||||||
"appId": "App ID",
|
"appId": "Alkalmazásazonosító",
|
||||||
"appWithIdOrNameNotFound": "Nem található app ezzel az azonosítóval vagy névvel",
|
"appWithIdOrNameNotFound": "Nem található app ezzel az azonosítóval vagy névvel",
|
||||||
"reposHaveMultipleApps": "A repók több alkalmazást is tartalmazhatnak",
|
"reposHaveMultipleApps": "A repók több alkalmazást is tartalmazhatnak",
|
||||||
"fdroidThirdPartyRepo": "F-Droid Harmadik-fél Repo",
|
"fdroidThirdPartyRepo": "F-Droid Harmadik-fél Repo",
|
||||||
"steam": "Steam",
|
"steamMobile": "Steam mobil",
|
||||||
"steamMobile": "Steam Mobile",
|
|
||||||
"steamChat": "Steam Chat",
|
"steamChat": "Steam Chat",
|
||||||
"install": "Telepít",
|
"install": "Telepít",
|
||||||
"markInstalled": "Telepítettnek jelöl",
|
"markInstalled": "Telepítettnek jelöl",
|
||||||
@ -194,7 +192,7 @@
|
|||||||
"category": "Kategória",
|
"category": "Kategória",
|
||||||
"noCategory": "Nincs kategória",
|
"noCategory": "Nincs kategória",
|
||||||
"noCategories": "Nincsenek kategóriák",
|
"noCategories": "Nincsenek kategóriák",
|
||||||
"deleteCategoryQuestion": "Törli a kategóriát?",
|
"deleteCategoriesQuestion": "Törli a kategóriákat?",
|
||||||
"categoryDeleteWarning": "A(z) {} összes app kategorizálatlan állapotba kerül.",
|
"categoryDeleteWarning": "A(z) {} összes app kategorizálatlan állapotba kerül.",
|
||||||
"addCategory": "Új kategória",
|
"addCategory": "Új kategória",
|
||||||
"label": "Címke",
|
"label": "Címke",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Változtatások",
|
"changes": "Változtatások",
|
||||||
"releaseDate": "Kiadás dátuma",
|
"releaseDate": "Kiadás dátuma",
|
||||||
"importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)",
|
"importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)",
|
||||||
|
"versionDetectionExplanation": "A verzió karakterlánc egyeztetése az OS által észlelt verzióval",
|
||||||
"versionDetection": "Verzió érzékelés",
|
"versionDetection": "Verzió érzékelés",
|
||||||
"standardVersionDetection": "Alapért. verzió érzékelés",
|
"standardVersionDetection": "Alapért. verzió érzékelés",
|
||||||
"groupByCategory": "Csoportosítás Kategória alapján",
|
"groupByCategory": "Csoportosítás Kategória alapján",
|
||||||
@ -241,13 +240,14 @@
|
|||||||
"appsPossiblyUpdated": "App frissítési kísérlet",
|
"appsPossiblyUpdated": "App frissítési kísérlet",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy vagy több alkalmazás frissítése lehetséges a háttérben",
|
"appsPossiblyUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy vagy több alkalmazás frissítése lehetséges a háttérben",
|
||||||
"xWasPossiblyUpdatedToY": "{} frissítve lehet erre {}.",
|
"xWasPossiblyUpdatedToY": "{} frissítve lehet erre {}.",
|
||||||
|
"enableBackgroundUpdates": "Frissítések a háttérben",
|
||||||
"backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.",
|
"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.",
|
"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",
|
"verifyLatestTag": "Ellenőrizze a „legújabb” címkét",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Szűrés egy 'köztes' látogatási linkre",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "A hivatkozások szűrése linkszöveg alapján",
|
||||||
"intermediateLinkNotFound": "Közvetítő link nem található",
|
"intermediateLinkNotFound": "Köztes link nem található",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Köztes link",
|
||||||
"exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)",
|
"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",
|
"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",
|
"autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása",
|
||||||
@ -256,16 +256,15 @@
|
|||||||
"highlightTouchTargets": "Emelje ki a kevésbé nyilvánvaló érintési célokat",
|
"highlightTouchTargets": "Emelje ki a kevésbé nyilvánvaló érintési célokat",
|
||||||
"pickExportDir": "Válassza az Exportálási könyvtárat",
|
"pickExportDir": "Válassza az Exportálási könyvtárat",
|
||||||
"autoExportOnChanges": "Auto-exportálás a változások után",
|
"autoExportOnChanges": "Auto-exportálás a változások után",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Tartalmazza a beállításokat",
|
||||||
"filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel",
|
"filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel",
|
||||||
"trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t",
|
"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",
|
"dontSortReleasesList": "Az API-ból származó kiadási sorrend megőrzése",
|
||||||
"reverseSort": "Fordított rendezés",
|
"reverseSort": "Fordított rendezés",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Vegye az első linket",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "A válogatás kihagyása",
|
||||||
"debugMenu": "Hibakereső menü",
|
"debugMenu": "Hibakereső menü",
|
||||||
"bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.",
|
"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",
|
"runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most",
|
||||||
"versionExtractWholePage": "Alkalmazza a Version Extraction Regex-et az egész oldalra",
|
"versionExtractWholePage": "Alkalmazza a Version Extraction Regex-et az egész oldalra",
|
||||||
"installing": "Telepítés",
|
"installing": "Telepítés",
|
||||||
@ -282,14 +281,29 @@
|
|||||||
"supportFixedAPKURL": "Támogatja a rögzített APK URL-eket",
|
"supportFixedAPKURL": "Támogatja a rögzített APK URL-eket",
|
||||||
"selectX": "Kiválaszt {}",
|
"selectX": "Kiválaszt {}",
|
||||||
"parallelDownloads": "Párhuzamos letöltéseket enged",
|
"parallelDownloads": "Párhuzamos letöltéseket enged",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "Telepítési mód",
|
||||||
"normal": "Normal",
|
"normal": "Normál",
|
||||||
"shizuku": "Shizuku",
|
"root": "Gyökér",
|
||||||
"root": "Root",
|
"shizukuBinderNotFound": "A Shizuku nem fut",
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"useSystemFont": "Használja a rendszer betűtípusát",
|
||||||
|
"systemFontError": "Hiba a rendszer betűtípusának betöltésekor: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Az app verziókód használata a rendszer által észlelt verzióként",
|
||||||
|
"requestHeader": "Kérelem fejléc",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Használja a legújabb tartalomfeltöltést megjelenési dátumként",
|
||||||
|
"defaultPseudoVersioningMethod": "Alapértelmezett álversziós módszer",
|
||||||
|
"partialAPKHash": "Részleges APK Hash",
|
||||||
|
"APKLinkHash": "APK Link Hash",
|
||||||
|
"directAPKLink": "Közvetlen APK Link",
|
||||||
|
"pseudoVersionInUse": "Egy álverzió van használatban",
|
||||||
|
"installed": "Telepített",
|
||||||
|
"latest": "Legújabb",
|
||||||
|
"invertRegEx": "Invertált reguláris kifejezés",
|
||||||
|
"note": "Megjegyzés:",
|
||||||
|
"selfHostedNote": "A \"{}\" legördülő menü használható bármely forrás saját üzemeltetésű/egyéni példányainak eléréséhez.",
|
||||||
|
"badDownload": "Az APK-t nem lehetett elemezni (inkompatibilis vagy részleges letöltés)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Eltávolítja az alkalmazást?",
|
"one": "Eltávolítja az alkalmazást?",
|
||||||
"other": "Eltávolítja az alkalmazást?"
|
"other": "Eltávolítja az alkalmazásokat?"
|
||||||
},
|
},
|
||||||
"tooManyRequestsTryAgainInMinutes": {
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
"one": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva",
|
"one": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva",
|
||||||
|
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Avanzamento: {}%",
|
"percentProgress": "Avanzamento: {}%",
|
||||||
"pleaseWait": "In attesa",
|
"pleaseWait": "In attesa",
|
||||||
"updateAvailable": "Aggiornamento disponibile",
|
"updateAvailable": "Aggiornamento disponibile",
|
||||||
"estimateInBracketsShort": "(stim.)",
|
|
||||||
"notInstalled": "Non installato",
|
"notInstalled": "Non installato",
|
||||||
"estimateInBrackets": "(stimato)",
|
"pseudoVersion": "pseudo-versione",
|
||||||
"selectAll": "Seleziona tutto",
|
"selectAll": "Seleziona tutto",
|
||||||
"deselectX": "Deseleziona {}",
|
"deselectX": "Deseleziona {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "Verà effettuata la rimozione di {}, ma non la disinstallazione.",
|
"xWillBeRemovedButRemainInstalled": "Verà effettuata la rimozione di {}, ma non la disinstallazione.",
|
||||||
@ -66,13 +65,15 @@
|
|||||||
"installUpdateApps": "Installa/Aggiorna app",
|
"installUpdateApps": "Installa/Aggiorna app",
|
||||||
"installUpdateSelectedApps": "Installa/Aggiorna le app selezionate",
|
"installUpdateSelectedApps": "Installa/Aggiorna le app selezionate",
|
||||||
"markXSelectedAppsAsUpdated": "Contrassegnare le {} app selezionate come aggiornate?",
|
"markXSelectedAppsAsUpdated": "Contrassegnare le {} app selezionate come aggiornate?",
|
||||||
"no": "No",
|
"no": "NO",
|
||||||
"yes": "Sì",
|
"yes": "Sì",
|
||||||
"markSelectedAppsUpdated": "Contrassegna le app selezionate come aggiornate",
|
"markSelectedAppsUpdated": "Contrassegna le app selezionate come aggiornate",
|
||||||
"pinToTop": "Fissa in alto",
|
"pinToTop": "Fissa in alto",
|
||||||
"unpinFromTop": "Rimuovi dall'alto",
|
"unpinFromTop": "Rimuovi dall'alto",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Ripristinare lo stato d'installazione delle app selezionate?",
|
"resetInstallStatusForSelectedAppsQuestion": "Ripristinare lo stato d'installazione delle app selezionate?",
|
||||||
"installStatusOfXWillBeResetExplanation": "Lo stato d'installazione di ogni app selezionata sarà ripristinato.\n\nCiò può essere d'aiuto nel caso in cui la versione mostrata dell'app in Obtainium non sia corretta a causa di un aggiornamento fallito o di altri problemi.",
|
"installStatusOfXWillBeResetExplanation": "Lo stato d'installazione di ogni app selezionata sarà ripristinato.\n\nCiò può essere d'aiuto nel caso in cui la versione mostrata dell'app in Obtainium non sia corretta a causa di un aggiornamento fallito o di altri problemi.",
|
||||||
|
"customLinkMessage": "Questi collegamenti funzionano sui dispositivi con Obtainium installato",
|
||||||
|
"shareAppConfigLinks": "Condividi la configurazione dell'app come collegamento HTML",
|
||||||
"shareSelectedAppURLs": "Condividi gli URL delle app selezionate",
|
"shareSelectedAppURLs": "Condividi gli URL delle app selezionate",
|
||||||
"resetInstallStatus": "Ripristina lo stato d'installazione",
|
"resetInstallStatus": "Ripristina lo stato d'installazione",
|
||||||
"more": "Altro",
|
"more": "Altro",
|
||||||
@ -110,9 +111,7 @@
|
|||||||
"dark": "Scuro",
|
"dark": "Scuro",
|
||||||
"light": "Chiaro",
|
"light": "Chiaro",
|
||||||
"followSystem": "Segui il sistema",
|
"followSystem": "Segui il sistema",
|
||||||
"obtainium": "Obtainium",
|
"useBlackTheme": "Usa il tema nero puro",
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Usa il tema Nero puro",
|
|
||||||
"appSortBy": "App ordinate per",
|
"appSortBy": "App ordinate per",
|
||||||
"authorName": "Autore/Nome",
|
"authorName": "Autore/Nome",
|
||||||
"nameAuthor": "Nome/Autore",
|
"nameAuthor": "Nome/Autore",
|
||||||
@ -175,9 +174,8 @@
|
|||||||
"appWithIdOrNameNotFound": "Non è stata trovata alcuna app con quell'ID o nome",
|
"appWithIdOrNameNotFound": "Non è stata trovata alcuna app con quell'ID o nome",
|
||||||
"reposHaveMultipleApps": "I repository possono contenere più app",
|
"reposHaveMultipleApps": "I repository possono contenere più app",
|
||||||
"fdroidThirdPartyRepo": "Repository F-Droid di terze parti",
|
"fdroidThirdPartyRepo": "Repository F-Droid di terze parti",
|
||||||
"steam": "Steam",
|
"steamMobile": "Mobile a vapore",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "Chat di vapore",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "Installa",
|
"install": "Installa",
|
||||||
"markInstalled": "Contrassegna come installata",
|
"markInstalled": "Contrassegna come installata",
|
||||||
"update": "Aggiorna",
|
"update": "Aggiorna",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Novità",
|
"changes": "Novità",
|
||||||
"releaseDate": "Data di rilascio",
|
"releaseDate": "Data di rilascio",
|
||||||
"importFromURLsInFile": "Importa da URL in file (come OPML)",
|
"importFromURLsInFile": "Importa da URL in file (come OPML)",
|
||||||
|
"versionDetectionExplanation": "Riconcilia la stringa della versione con la versione rilevata dal sistema operativo",
|
||||||
"versionDetection": "Rilevamento di versione",
|
"versionDetection": "Rilevamento di versione",
|
||||||
"standardVersionDetection": "Rilevamento di versione standard",
|
"standardVersionDetection": "Rilevamento di versione standard",
|
||||||
"groupByCategory": "Raggruppa per categoria",
|
"groupByCategory": "Raggruppa per categoria",
|
||||||
@ -235,7 +234,7 @@
|
|||||||
"addInfoInSettings": "Aggiungi questa info nelle impostazioni.",
|
"addInfoInSettings": "Aggiungi questa info nelle impostazioni.",
|
||||||
"githubSourceNote": "Il limite di ricerca GitHub può essere evitato usando una chiave API.",
|
"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.",
|
"gitlabSourceNote": "L'estrazione di APK da GitLab potrebbe non funzionare senza chiave API.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Ordina solo in base all'ultimo segmento del collegamento",
|
||||||
"filterReleaseNotesByRegEx": "Filtra le note di rilascio con espressione regolare",
|
"filterReleaseNotesByRegEx": "Filtra le note di rilascio con espressione regolare",
|
||||||
"customLinkFilterRegex": "Filtra link APK personalizzato con espressione regolare (predefinito '.apk$')",
|
"customLinkFilterRegex": "Filtra link APK personalizzato con espressione regolare (predefinito '.apk$')",
|
||||||
"appsPossiblyUpdated": "Aggiornamenti app tentati",
|
"appsPossiblyUpdated": "Aggiornamenti app tentati",
|
||||||
@ -245,10 +244,10 @@
|
|||||||
"backgroundUpdateReqsExplanation": "Gli aggiornamenti in secondo piano potrebbero non essere possibili per tutte le app.",
|
"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.",
|
"backgroundUpdateLimitsExplanation": "La riuscita di un'installazione in secondo piano può essere determinata solo quando viene aperto Obtainium.",
|
||||||
"verifyLatestTag": "Verifica l'etichetta 'Latest'",
|
"verifyLatestTag": "Verifica l'etichetta 'Latest'",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Filtro per un collegamento 'intermedio' da visitare",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Filtra i collegamenti in base al testo del collegamento",
|
||||||
"intermediateLinkNotFound": "Link intermedio non trovato",
|
"intermediateLinkNotFound": "Link intermedio non trovato",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Collegamento intermedio",
|
||||||
"exemptFromBackgroundUpdates": "Esente da aggiornamenti in secondo piano (se attivo)",
|
"exemptFromBackgroundUpdates": "Esente da aggiornamenti in secondo piano (se attivo)",
|
||||||
"bgUpdatesOnWiFiOnly": "Disattiva aggiornamenti in secondo piano quando non si usa il WiFi",
|
"bgUpdatesOnWiFiOnly": "Disattiva aggiornamenti in secondo piano quando non si usa il WiFi",
|
||||||
"autoSelectHighestVersionCode": "Auto-seleziona APK con versionCode più alto",
|
"autoSelectHighestVersionCode": "Auto-seleziona APK con versionCode più alto",
|
||||||
@ -284,9 +283,24 @@
|
|||||||
"parallelDownloads": "Permetti download paralleli",
|
"parallelDownloads": "Permetti download paralleli",
|
||||||
"installMethod": "Metodo d'installazione",
|
"installMethod": "Metodo d'installazione",
|
||||||
"normal": "Normale",
|
"normal": "Normale",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Root",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "Shizuku non è in esecuzione",
|
"shizukuBinderNotFound": "Shizuku non è in esecuzione",
|
||||||
|
"useSystemFont": "Usa i caratteri di sistema",
|
||||||
|
"systemFontError": "Errore durante il caricamento dei caratteri di sistema: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Usa il codice versione dell'app come versione rilevata dal sistema operativo",
|
||||||
|
"requestHeader": "Intestazione della richiesta",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Usa l'ultimo caricamento della risorsa come data di rilascio",
|
||||||
|
"defaultPseudoVersioningMethod": "Metodo di pseudoversione predefinito",
|
||||||
|
"partialAPKHash": "Hash APK parziale",
|
||||||
|
"APKLinkHash": "Hash collegamento APK",
|
||||||
|
"directAPKLink": "Collegamento APK diretto",
|
||||||
|
"pseudoVersionInUse": "È in uso una pseudo-versione",
|
||||||
|
"installed": "Installato",
|
||||||
|
"latest": "Ultimo",
|
||||||
|
"invertRegEx": "Inverti espressione regolare",
|
||||||
|
"note": "Nota",
|
||||||
|
"selfHostedNote": "Il menu a tendina \"{}\" può essere usato per raggiungere istanze autogestite/personali di qualsiasi fonte.",
|
||||||
|
"badDownload": "Non è stato possibile analizzare l'APK (download incompatibile o parziale).",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Rimuovere l'app?",
|
"one": "Rimuovere l'app?",
|
||||||
"other": "Rimuovere le app?"
|
"other": "Rimuovere le app?"
|
||||||
|
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "ダウンロード中: {}%",
|
"percentProgress": "ダウンロード中: {}%",
|
||||||
"pleaseWait": "しばらくお待ちください",
|
"pleaseWait": "しばらくお待ちください",
|
||||||
"updateAvailable": "アップデートが利用可能",
|
"updateAvailable": "アップデートが利用可能",
|
||||||
"estimateInBracketsShort": "(推定)",
|
|
||||||
"notInstalled": "未インストール",
|
"notInstalled": "未インストール",
|
||||||
"estimateInBrackets": "(推定)",
|
"pseudoVersion": "疑似バージョン",
|
||||||
"selectAll": "すべて選択",
|
"selectAll": "すべて選択",
|
||||||
"deselectX": "{}件の選択を解除",
|
"deselectX": "{}件の選択を解除",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} はObtainiumから削除されますが、デバイスにはインストールされたままです。",
|
"xWillBeRemovedButRemainInstalled": "{} はObtainiumから削除されますが、デバイスにはインストールされたままです。",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "トップから固定解除",
|
"unpinFromTop": "トップから固定解除",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "選択したアプリのインストール状態をリセットしますか?",
|
"resetInstallStatusForSelectedAppsQuestion": "選択したアプリのインストール状態をリセットしますか?",
|
||||||
"installStatusOfXWillBeResetExplanation": "選択したアプリのインストール状態がリセットされます。\n\nアップデートに失敗した場合など、Obtainiumに表示されるアプリのバージョンが正しくない場合に有効です。",
|
"installStatusOfXWillBeResetExplanation": "選択したアプリのインストール状態がリセットされます。\n\nアップデートに失敗した場合など、Obtainiumに表示されるアプリのバージョンが正しくない場合に有効です。",
|
||||||
|
"customLinkMessage": "これらのリンクはObtainiumがインストールされたデバイスで動作します",
|
||||||
|
"shareAppConfigLinks": "アプリの設定をHTMLリンクとして共有する",
|
||||||
"shareSelectedAppURLs": "選択したアプリのURLを共有する",
|
"shareSelectedAppURLs": "選択したアプリのURLを共有する",
|
||||||
"resetInstallStatus": "インストール状態をリセットする",
|
"resetInstallStatus": "インストール状態をリセットする",
|
||||||
"more": "もっと見る",
|
"more": "もっと見る",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "ダーク",
|
"dark": "ダーク",
|
||||||
"light": "ライト",
|
"light": "ライト",
|
||||||
"followSystem": "システムに従う",
|
"followSystem": "システムに従う",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "ピュアブラックダークテーマを使用する",
|
"useBlackTheme": "ピュアブラックダークテーマを使用する",
|
||||||
"appSortBy": "アプリの並び方",
|
"appSortBy": "アプリの並び方",
|
||||||
"authorName": "作者名/アプリ名",
|
"authorName": "作者名/アプリ名",
|
||||||
@ -153,8 +152,8 @@
|
|||||||
"appsRemovedNotifDescription": "アプリの読み込み中にエラーが発生したため、1つまたは複数のアプリが削除されたことをユーザーに通知する",
|
"appsRemovedNotifDescription": "アプリの読み込み中にエラーが発生したため、1つまたは複数のアプリが削除されたことをユーザーに通知する",
|
||||||
"xWasRemovedDueToErrorY": "このエラーのため、{} は削除されました: {}",
|
"xWasRemovedDueToErrorY": "このエラーのため、{} は削除されました: {}",
|
||||||
"completeAppInstallation": "アプリのインストールを完了する",
|
"completeAppInstallation": "アプリのインストールを完了する",
|
||||||
"obtainiumMustBeOpenToInstallApps": "アプリをインストールするにはObtainiumを開いている必要があります。",
|
"obtainiumMustBeOpenToInstallApps": "アプリをインストールするにはObtainiumが開いている必要があります",
|
||||||
"completeAppInstallationNotifDescription": "アプリのインストールを完了するために、Obtainiumに戻る必要があります。",
|
"completeAppInstallationNotifDescription": "アプリのインストールを完了するために、Obtainiumに戻る必要があります",
|
||||||
"checkingForUpdates": "アップデートを確認中",
|
"checkingForUpdates": "アップデートを確認中",
|
||||||
"checkingForUpdatesNotifDescription": "アップデートを確認する際に表示される一時的な通知",
|
"checkingForUpdatesNotifDescription": "アップデートを確認する際に表示される一時的な通知",
|
||||||
"pleaseAllowInstallPerm": "Obtainiumによるアプリのインストールを許可してください。",
|
"pleaseAllowInstallPerm": "Obtainiumによるアプリのインストールを許可してください。",
|
||||||
@ -169,15 +168,14 @@
|
|||||||
"lastUpdateCheckX": "最終アップデート確認: {}",
|
"lastUpdateCheckX": "最終アップデート確認: {}",
|
||||||
"remove": "削除",
|
"remove": "削除",
|
||||||
"yesMarkUpdated": "はい、アップデート済みとしてマークします",
|
"yesMarkUpdated": "はい、アップデート済みとしてマークします",
|
||||||
"fdroid": "F-Droid Official",
|
"fdroid": "F-Droid公式",
|
||||||
"appIdOrName": "アプリのIDまたは名前",
|
"appIdOrName": "アプリのIDまたは名前",
|
||||||
"appId": "App ID",
|
"appId": "アプリID",
|
||||||
"appWithIdOrNameNotFound": "そのIDや名前を持つアプリは見つかりませんでした",
|
"appWithIdOrNameNotFound": "そのIDや名前を持つアプリは見つかりませんでした",
|
||||||
"reposHaveMultipleApps": "リポジトリには複数のアプリが含まれることがあります",
|
"reposHaveMultipleApps": "リポジトリには複数のアプリが含まれることがあります",
|
||||||
"fdroidThirdPartyRepo": "F-Droid サードパーティリポジトリ",
|
"fdroidThirdPartyRepo": "F-Droid サードパーティリポジトリ",
|
||||||
"steam": "Steam",
|
"steamMobile": "Steamモバイル",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "Steamチャット",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "インストール",
|
"install": "インストール",
|
||||||
"markInstalled": "インストール済みとしてマークする",
|
"markInstalled": "インストール済みとしてマークする",
|
||||||
"update": "アップデート",
|
"update": "アップデート",
|
||||||
@ -211,10 +209,11 @@
|
|||||||
"changes": "変更点",
|
"changes": "変更点",
|
||||||
"releaseDate": "リリース日",
|
"releaseDate": "リリース日",
|
||||||
"importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート",
|
"importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート",
|
||||||
|
"versionDetectionExplanation": "バージョン文字列とOSから検出されたバージョンを照合する",
|
||||||
"versionDetection": "バージョン検出",
|
"versionDetection": "バージョン検出",
|
||||||
"standardVersionDetection": "標準のバージョン検出",
|
"standardVersionDetection": "標準のバージョン検出",
|
||||||
"groupByCategory": "カテゴリ別にグループ化する",
|
"groupByCategory": "カテゴリ別にグループ化する",
|
||||||
"autoApkFilterByArch": "可能であれば,CPUアーキテクチャによるAPKのフィルタリングを試みる",
|
"autoApkFilterByArch": "可能であれば、CPUアーキテクチャによるAPKのフィルタリングを試みる",
|
||||||
"overrideSource": "ソースの上書き",
|
"overrideSource": "ソースの上書き",
|
||||||
"dontShowAgain": "二度と表示しない",
|
"dontShowAgain": "二度と表示しない",
|
||||||
"dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない",
|
"dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない",
|
||||||
@ -250,14 +249,14 @@
|
|||||||
"intermediateLinkNotFound": "中間リンクが見つかりませんでした",
|
"intermediateLinkNotFound": "中間リンクが見つかりませんでした",
|
||||||
"intermediateLink": "中間リンク",
|
"intermediateLink": "中間リンク",
|
||||||
"exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)",
|
"exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)",
|
||||||
"bgUpdatesOnWiFiOnly": "WiFiを使用していない場合,バックグラウンドアップデートを無効にする",
|
"bgUpdatesOnWiFiOnly": "WiFiを使用していない場合、バックグラウンドアップデートを無効にする",
|
||||||
"autoSelectHighestVersionCode": "最も高いバージョンコードのAPKを自動で選択する",
|
"autoSelectHighestVersionCode": "最も高いバージョンコードのAPKを自動で選択する",
|
||||||
"versionExtractionRegEx": "バージョン抽出の正規表現",
|
"versionExtractionRegEx": "バージョン抽出の正規表現",
|
||||||
"matchGroupToUse": "使用するマッチしたグループ",
|
"matchGroupToUse": "使用するマッチしたグループ",
|
||||||
"highlightTouchTargets": "目立たないタップ可能な対象をハイライトする",
|
"highlightTouchTargets": "目立たないタップ可能な対象をハイライトする",
|
||||||
"pickExportDir": "エクスポートディレクトリを選択",
|
"pickExportDir": "エクスポートディレクトリを選択",
|
||||||
"autoExportOnChanges": "変更があった際に自動でエクスポートする",
|
"autoExportOnChanges": "変更があった際に自動でエクスポートする",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "設定を含む",
|
||||||
"filterVersionsByRegEx": "正規表現でバージョンをフィルタリングする",
|
"filterVersionsByRegEx": "正規表現でバージョンをフィルタリングする",
|
||||||
"trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する",
|
"trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する",
|
||||||
"dontSortReleasesList": "APIからのリリース順を保持する",
|
"dontSortReleasesList": "APIからのリリース順を保持する",
|
||||||
@ -284,9 +283,24 @@
|
|||||||
"parallelDownloads": "並行ダウンロードを許可する",
|
"parallelDownloads": "並行ダウンロードを許可する",
|
||||||
"installMethod": "インストール方法",
|
"installMethod": "インストール方法",
|
||||||
"normal": "通常",
|
"normal": "通常",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Root",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "Shizukuが起動していません",
|
"shizukuBinderNotFound": "Shizukuが起動していません",
|
||||||
|
"useSystemFont": "システムフォントを使用する",
|
||||||
|
"systemFontError": "システムフォントの読み込みエラー: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "アプリのバージョンコードをOSで検出されたバージョンとして使用する",
|
||||||
|
"requestHeader": "リクエストヘッダー",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "最新のアセットアップロードをリリース日として使用する",
|
||||||
|
"defaultPseudoVersioningMethod": "デフォルトの疑似バージョン管理方法",
|
||||||
|
"partialAPKHash": "部分的なAPKのハッシュ",
|
||||||
|
"APKLinkHash": "APKリンクのハッシュ",
|
||||||
|
"directAPKLink": "APKのダイレクトリンク",
|
||||||
|
"pseudoVersionInUse": "疑似バージョンが使用されています",
|
||||||
|
"installed": "インストール済み",
|
||||||
|
"latest": "最新",
|
||||||
|
"invertRegEx": "正規表現を反転",
|
||||||
|
"note": "注",
|
||||||
|
"selfHostedNote": "ドロップダウン\"{}\"を使用すると、あらゆるソースのセルフホスト/カスタムインスタンスにアクセスできます。",
|
||||||
|
"badDownload": "APK を解析できませんでした(互換性がないか、部分的にダウンロードされています)。",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "アプリを削除しますか?",
|
"one": "アプリを削除しますか?",
|
||||||
"other": "アプリを削除しますか?"
|
"other": "アプリを削除しますか?"
|
||||||
|
@ -1,342 +1,356 @@
|
|||||||
{
|
{
|
||||||
"invalidURLForSource": "Geen valide {} app URL",
|
"invalidURLForSource": "Geen valide {} app URL",
|
||||||
"noReleaseFound": "Kan geen geschikte release vinden",
|
"noReleaseFound": "Kan geen geschikte release vinden",
|
||||||
"noVersionFound": "Kan de versie niet bepalen",
|
"noVersionFound": "Kan de versie niet bepalen",
|
||||||
"urlMatchesNoSource": "URL komt niet overeen met bekende bron",
|
"urlMatchesNoSource": "URL komt niet overeen met bekende bron",
|
||||||
"cantInstallOlderVersion": "Kan geen oudere versie van de app installeren",
|
"cantInstallOlderVersion": "Kan geen oudere versie van de app installeren",
|
||||||
"appIdMismatch": "Gedownloade pakket-ID komt niet overeen met de bestaande app-ID",
|
"appIdMismatch": "Gedownloade pakket-ID komt niet overeen met de bestaande app-ID",
|
||||||
"functionNotImplemented": "Deze class heeft deze functie niet geïmplementeerd.",
|
"functionNotImplemented": "Deze class heeft deze functie niet geïmplementeerd.",
|
||||||
"placeholder": "Plaatshouder",
|
"placeholder": "Plaatshouder",
|
||||||
"someErrors": "Er zijn enkele fouten opgetreden",
|
"someErrors": "Er zijn enkele fouten opgetreden",
|
||||||
"unexpectedError": "Onverwachte fout",
|
"unexpectedError": "Onverwachte fout",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"and": "en",
|
"and": "en",
|
||||||
"githubPATLabel": "GitHub Personal Access Token\n(Verhoogt limiet aantal verzoeken)",
|
"githubPATLabel": "GitHub Personal Access Token\n(Verhoogt limiet aantal verzoeken)",
|
||||||
"includePrereleases": "Bevat prereleases",
|
"includePrereleases": "Bevat prereleases",
|
||||||
"fallbackToOlderReleases": "Terugvallen op oudere releases",
|
"fallbackToOlderReleases": "Terugvallen op oudere releases",
|
||||||
"filterReleaseTitlesByRegEx": "Filter release-titels met reguliere expressies.",
|
"filterReleaseTitlesByRegEx": "Filter release-titels met reguliere expressies.",
|
||||||
"invalidRegEx": "Ongeldige reguliere expressie",
|
"invalidRegEx": "Ongeldige reguliere expressie",
|
||||||
"noDescription": "Geen omschrijving",
|
"noDescription": "Geen omschrijving",
|
||||||
"cancel": "Annuleer",
|
"cancel": "Annuleer",
|
||||||
"continue": "Ga verder",
|
"continue": "Ga verder",
|
||||||
"requiredInBrackets": "(Verplicht)",
|
"requiredInBrackets": "(Verplicht)",
|
||||||
"dropdownNoOptsError": "FOUTMELDING: DROPDOWN MOET TENMINSTE ÉÉN OPT HEBBEN",
|
"dropdownNoOptsError": "FOUTMELDING: DROPDOWN MOET TENMINSTE ÉÉN OPT HEBBEN",
|
||||||
"colour": "Kleur",
|
"colour": "Kleur",
|
||||||
"githubStarredRepos": "GitHub Starred Repos",
|
"githubStarredRepos": "GitHub-repo's met ster",
|
||||||
"uname": "Gebruikersnaam",
|
"uname": "Gebruikersnaam",
|
||||||
"wrongArgNum": "Onjuist aantal argumenten verstrekt.",
|
"wrongArgNum": "Onjuist aantal argumenten verstrekt.",
|
||||||
"xIsTrackOnly": "{} is Track-Only",
|
"xIsTrackOnly": "{} is alleen tracken",
|
||||||
"source": "Bron",
|
"source": "Bron",
|
||||||
"app": "App",
|
"app": "App",
|
||||||
"appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Track-Only'.",
|
"appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Track-Only'.",
|
||||||
"youPickedTrackOnly": "Je hebt de 'Track-Only' optie geselecteerd.",
|
"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.",
|
"trackOnlyAppDescription": "De app zal worden gevolgd voor updates, maar Obtainium zal niet in staat zijn om deze te downloaden of te installeren.",
|
||||||
"cancelled": "Geannuleerd",
|
"cancelled": "Geannuleerd",
|
||||||
"appAlreadyAdded": "App al toegevoegd",
|
"appAlreadyAdded": "App al toegevoegd",
|
||||||
"alreadyUpToDateQuestion": "Is de app al up-to-date?",
|
"alreadyUpToDateQuestion": "Is de app al up-to-date?",
|
||||||
"addApp": "App toevoegen",
|
"addApp": "App toevoegen",
|
||||||
"appSourceURL": "App bron URL",
|
"appSourceURL": "App bron URL",
|
||||||
"error": "Foutmelding",
|
"error": "Foutmelding",
|
||||||
"add": "Toevoegen",
|
"add": "Toevoegen",
|
||||||
"searchSomeSourcesLabel": "Zoeken (Alleen sommige bronnen)",
|
"searchSomeSourcesLabel": "Zoeken (Alleen sommige bronnen)",
|
||||||
"search": "Zoeken",
|
"search": "Zoeken",
|
||||||
"additionalOptsFor": "Aanvullende opties voor {}",
|
"additionalOptsFor": "Aanvullende opties voor {}",
|
||||||
"supportedSources": "Ondersteunde bronnen",
|
"supportedSources": "Ondersteunde bronnen",
|
||||||
"trackOnlyInBrackets": "(Track-Only)",
|
"trackOnlyInBrackets": "(Alleen track)",
|
||||||
"searchableInBrackets": "(Doorzoekbaar)",
|
"searchableInBrackets": "(Doorzoekbaar)",
|
||||||
"appsString": "Apps",
|
"appsString": "Apps",
|
||||||
"noApps": "Geen Apps",
|
"noApps": "Geen Apps",
|
||||||
"noAppsForFilter": "Geen Apps voor filter",
|
"noAppsForFilter": "Geen Apps voor filter",
|
||||||
"byX": "Door {}",
|
"byX": "Door {}",
|
||||||
"percentProgress": "Vooruitgang: {}%",
|
"percentProgress": "Vooruitgang: {}%",
|
||||||
"pleaseWait": "Even geduld",
|
"pleaseWait": "Even geduld",
|
||||||
"updateAvailable": "Update beschikbaar",
|
"updateAvailable": "Update beschikbaar",
|
||||||
"estimateInBracketsShort": "(Ong.)",
|
"notInstalled": "Niet geinstalleerd",
|
||||||
"notInstalled": "Niet geinstalleerd",
|
"pseudoVersion": "pseudo-versie",
|
||||||
"estimateInBrackets": "(Ongeveer)",
|
"selectAll": "Selecteer alles",
|
||||||
"selectAll": "Selecteer alles",
|
"deselectX": "Deselecteer {}",
|
||||||
"deselectX": "Deselecteer {}",
|
"xWillBeRemovedButRemainInstalled": "{} zal worden verwijderd uit Obtainium, maar blijft geïnstalleerd op het apparaat.",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} zal worden verwijderd uit Obtainium, maar blijft geïnstalleerd op het apparaat.",
|
"removeSelectedAppsQuestion": "Geselecteerde apps verwijderen??",
|
||||||
"removeSelectedAppsQuestion": "Geselecteerde apps verwijderen??",
|
"removeSelectedApps": "Geselecteerde apps verwijderen",
|
||||||
"removeSelectedApps": "Geselecteerde apps verwijderen",
|
"updateX": "Update {}",
|
||||||
"updateX": "Update {}",
|
"installX": "Installeer {}",
|
||||||
"installX": "Installeer {}",
|
"markXTrackOnlyAsUpdated": "Markeer {}\n(Track-Only)\nals up-to-date",
|
||||||
"markXTrackOnlyAsUpdated": "Markeer {}\n(Track-Only)\nals up-to-date",
|
"changeX": "Verander {}",
|
||||||
"changeX": "Verander {}",
|
"installUpdateApps": "Installeer/Update apps",
|
||||||
"installUpdateApps": "Installeer/Update apps",
|
"installUpdateSelectedApps": "Installeer/Update geselecteerde apps",
|
||||||
"installUpdateSelectedApps": "Installeer/Update geselecteerde apps",
|
"markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als up-to-date?",
|
||||||
"markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als up-to-date?",
|
"no": "Nee",
|
||||||
"no": "Nee",
|
"yes": "Ja",
|
||||||
"yes": "Ja",
|
"markSelectedAppsUpdated": "Markeer geselecteerde aps als up-to-date",
|
||||||
"markSelectedAppsUpdated": "Markeer geselecteerde aps als up-to-date",
|
"pinToTop": "Vastzetten aan de bovenkant",
|
||||||
"pinToTop": "Vastzetten aan de bovenkant",
|
"unpinFromTop": "Losmaken van de bovenkant",
|
||||||
"unpinFromTop": "Losmaken van de bovenkant",
|
"resetInstallStatusForSelectedAppsQuestion": "Installatiestatus resetten voor geselecteerde apps?",
|
||||||
"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.",
|
||||||
"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.",
|
"customLinkMessage": "Deze links werken op apparaten waarop Obtainium is geïnstalleerd",
|
||||||
"shareSelectedAppURLs": "Deel geselecteerde app URL's",
|
"shareAppConfigLinks": "App-configuratie delen als HTML-link",
|
||||||
"resetInstallStatus": "Reset installatiestatus",
|
"shareSelectedAppURLs": "Deel geselecteerde app URL's",
|
||||||
"more": "Meer",
|
"resetInstallStatus": "Reset installatiestatus",
|
||||||
"removeOutdatedFilter": "Verwijder out-of-date app filter",
|
"more": "Meer",
|
||||||
"showOutdatedOnly": "Toon alleen out-of-date apps",
|
"removeOutdatedFilter": "Verwijder out-of-date app filter",
|
||||||
"filter": "Filter",
|
"showOutdatedOnly": "Toon alleen out-of-date apps",
|
||||||
"filterActive": "Filter *",
|
"filter": "Filter",
|
||||||
"filterApps": "Filter apps",
|
"filterActive": "Filteren *",
|
||||||
"appName": "App naam",
|
"filterApps": "Filter apps",
|
||||||
"author": "Auteur",
|
"appName": "App naam",
|
||||||
"upToDateApps": "Up-to-date apps",
|
"author": "Auteur",
|
||||||
"nonInstalledApps": "Niet-geïnstalleerde apps",
|
"upToDateApps": "Up-to-date apps",
|
||||||
"importExport": "Import/Export",
|
"nonInstalledApps": "Niet-geïnstalleerde apps",
|
||||||
"settings": "Instellingen",
|
"importExport": "Importeren/Exporteren",
|
||||||
"exportedTo": "Geëxporteerd naar {}",
|
"settings": "Instellingen",
|
||||||
"obtainiumExport": "Obtainium export",
|
"exportedTo": "Geëxporteerd naar {}",
|
||||||
"invalidInput": "Ongeldige invoer",
|
"obtainiumExport": "Obtainium export",
|
||||||
"importedX": "Geïmporteerd {}",
|
"invalidInput": "Ongeldige invoer",
|
||||||
"obtainiumImport": "Obtainium import",
|
"importedX": "Geïmporteerd {}",
|
||||||
"importFromURLList": "Importeer van URL-lijsten",
|
"obtainiumImport": "Obtainium import",
|
||||||
"searchQuery": "Zoekopdracht",
|
"importFromURLList": "Importeer van URL-lijsten",
|
||||||
"appURLList": "App URL-lijst",
|
"searchQuery": "Zoekopdracht",
|
||||||
"line": "Lijn",
|
"appURLList": "App URL-lijst",
|
||||||
"searchX": "Zoek {}",
|
"line": "Lijn",
|
||||||
"noResults": "Geen resultaten gevonden",
|
"searchX": "Zoek {}",
|
||||||
"importX": "Import {}",
|
"noResults": "Geen resultaten gevonden",
|
||||||
"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.",
|
"importX": "Importeer {}",
|
||||||
"importErrors": "Import foutmeldingen",
|
"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.",
|
||||||
"importedXOfYApps": "{} van {} apps geïmporteerd.",
|
"importErrors": "Import foutmeldingen",
|
||||||
"followingURLsHadErrors": "De volgende URL's bevatten fouten:",
|
"importedXOfYApps": "{} van {} apps geïmporteerd.",
|
||||||
"selectURL": "Selecteer URL",
|
"followingURLsHadErrors": "De volgende URL's bevatten fouten:",
|
||||||
"selectURLs": "Selecteer URL's",
|
"selectURL": "Selecteer URL",
|
||||||
"pick": "Kies",
|
"selectURLs": "Selecteer URL's",
|
||||||
"theme": "Thema",
|
"pick": "Kies",
|
||||||
"dark": "Donker",
|
"theme": "Thema",
|
||||||
"light": "Licht",
|
"dark": "Donker",
|
||||||
"followSystem": "Volg systeem",
|
"light": "Licht",
|
||||||
"obtainium": "Obtainium",
|
"followSystem": "Volg systeem",
|
||||||
"materialYou": "Material You",
|
"useBlackTheme": "Gebruik zwart thema",
|
||||||
"useBlackTheme": "Gebruik zwart thema",
|
"appSortBy": "App sorteren op",
|
||||||
"appSortBy": "App sorteren op",
|
"authorName": "Auteur/Naam",
|
||||||
"authorName": "Auteur/Naam",
|
"nameAuthor": "Naam/Auteur",
|
||||||
"nameAuthor": "Naam/Auteur",
|
"asAdded": "Zoals toegevoegd",
|
||||||
"asAdded": "Zoals toegevoegd",
|
"appSortOrder": "App sorteervolgorde",
|
||||||
"appSortOrder": "App sorteervolgorde",
|
"ascending": "Oplopend",
|
||||||
"ascending": "Oplopend",
|
"descending": "Aflopend",
|
||||||
"descending": "Aflopend",
|
"bgUpdateCheckInterval": "Frequentie voor achtergrondupdatecontrole",
|
||||||
"bgUpdateCheckInterval": "Frequentie voor achtergrondupdatecontrole",
|
"neverManualOnly": "Nooit - Alleen handmatig",
|
||||||
"neverManualOnly": "Nooit - Alleen handmatig",
|
"appearance": "Weergave",
|
||||||
"appearance": "Weergave",
|
"showWebInAppView": "Toon de bronwebpagina in app-weergave",
|
||||||
"showWebInAppView": "Toon de bronwebpagina in app-weergave",
|
"pinUpdates": "Updates bovenaan in de apps-weergave vastpinnen",
|
||||||
"pinUpdates": "Updates bovenaan in de apps-weergave vastpinnen",
|
"updates": "Updates",
|
||||||
"updates": "Updates",
|
"sourceSpecific": "Bron-specifiek",
|
||||||
"sourceSpecific": "Bron-specifiek",
|
"appSource": "App bron",
|
||||||
"appSource": "App bron",
|
"noLogs": "Geen logs",
|
||||||
"noLogs": "Geen logs",
|
"appLogs": "App logs",
|
||||||
"appLogs": "App logs",
|
"close": "Sluiten",
|
||||||
"close": "Sluiten",
|
"share": "Delen",
|
||||||
"share": "Delen",
|
"appNotFound": "App niet gevonden",
|
||||||
"appNotFound": "App niet gevonden",
|
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"pickAnAPK": "Kies een APK",
|
||||||
"pickAnAPK": "Kies een APK",
|
"appHasMoreThanOnePackage": "{} heeft meer dan één package:",
|
||||||
"appHasMoreThanOnePackage": "{} heeft meer dan één package:",
|
"deviceSupportsXArch": "Jouw apparaat support de {} CPU-architectuur.",
|
||||||
"deviceSupportsXArch": "Jouw apparaat support de {} CPU-architectuur.",
|
"deviceSupportsFollowingArchs": "Je apparaat ondersteunt de volgende CPU-architecturen:",
|
||||||
"deviceSupportsFollowingArchs": "Je apparaat ondersteunt de volgende CPU-architecturen:",
|
"warning": "Waarschuwing",
|
||||||
"warning": "Waarschuwing",
|
"sourceIsXButPackageFromYPrompt": "De appbron is '{}' maar de release package komt van '{}'. Doorgaan?",
|
||||||
"sourceIsXButPackageFromYPrompt": "De appbron is '{}' maar de release package komt van '{}'. Doorgaan?",
|
"updatesAvailable": "Updates beschikbaar",
|
||||||
"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.",
|
||||||
"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.",
|
||||||
"noNewUpdates": "Geen nieuwe updates.",
|
"xHasAnUpdate": "{} heeft een update.",
|
||||||
"xHasAnUpdate": "{} heeft een update.",
|
"appsUpdated": "Apps bijgewerkt",
|
||||||
"appsUpdated": "Apps bijgewerkt",
|
"appsUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps in de achtergrond zijn toegepast.",
|
||||||
"appsUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps in de achtergrond zijn toegepast.",
|
"xWasUpdatedToY": "{} is bijgewerkt naar {}.",
|
||||||
"xWasUpdatedToY": "{} is bijgewerkt naar {}.",
|
"errorCheckingUpdates": "Fout bij het controleren op updates",
|
||||||
"errorCheckingUpdates": "Fout bij het controleren op updates",
|
"errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer het controleren op updates in de achtergrond mislukt",
|
||||||
"errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer het controleren op updates in de achtergrond mislukt",
|
"appsRemoved": "Apps verwijderd",
|
||||||
"appsRemoved": "Apps verwijderd",
|
"appsRemovedNotifDescription": "Stelt de gebruiker op de hoogte dat één of meer apps zijn verwijderd vanwege fouten tijdens het laden ervan",
|
||||||
"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: {}",
|
||||||
"xWasRemovedDueToErrorY": "{} is verwijderd vanwege deze foutmelding: {}",
|
"completeAppInstallation": "Complete app installatie",
|
||||||
"completeAppInstallation": "Complete app installatie",
|
"obtainiumMustBeOpenToInstallApps": "Obtainium moet geopend zijn om apps te installeren",
|
||||||
"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",
|
||||||
"completeAppInstallationNotifDescription": "Vraagt de gebruiker om terug te keren naar Obtainium om de installatie van een app af te ronden",
|
"checkingForUpdates": "Controleren op updates",
|
||||||
"checkingForUpdates": "Controleren op updates",
|
"checkingForUpdatesNotifDescription": "Tijdelijke melding die verschijnt tijdens het controleren op updates",
|
||||||
"checkingForUpdatesNotifDescription": "Tijdelijke melding die verschijnt tijdens het controleren op updates",
|
"pleaseAllowInstallPerm": "Sta Obtainium toe om apps te installeren",
|
||||||
"pleaseAllowInstallPerm": "Sta Obtainium toe om apps te installeren",
|
"trackOnly": "Alleen track",
|
||||||
"trackOnly": "Track-Only",
|
"errorWithHttpStatusCode": "Foutmelding {}",
|
||||||
"errorWithHttpStatusCode": "Foutmelding {}",
|
"versionCorrectionDisabled": "Versiecorrectie uitgeschakeld (de plug-in lijkt niet te werken)",
|
||||||
"versionCorrectionDisabled": "Versiecorrectie uitgeschakeld (de plug-in lijkt niet te werken)",
|
"unknown": "Onbekend",
|
||||||
"unknown": "Onbekend",
|
"none": "Geen",
|
||||||
"none": "Geen",
|
"never": "Nooit",
|
||||||
"never": "Nooit",
|
"latestVersionX": "Laatste versie: {}",
|
||||||
"latestVersionX": "Laatste versie: {}",
|
"installedVersionX": "Geïnstalleerde versie: {}",
|
||||||
"installedVersionX": "Geïnstalleerde versie: {}",
|
"lastUpdateCheckX": "Laatste updatecontrole: {}",
|
||||||
"lastUpdateCheckX": "Laatste updatecontrole: {}",
|
"remove": "Verwijderen",
|
||||||
"remove": "Verwijderen",
|
"yesMarkUpdated": "Ja, markeer als bijgewerkt",
|
||||||
"yesMarkUpdated": "Ja, markeer als bijgewerkt",
|
"fdroid": "F-Droid-ambtenaar",
|
||||||
"fdroid": "F-Droid Official",
|
"appIdOrName": "App ID of naam",
|
||||||
"appIdOrName": "App ID of naam",
|
"appId": "App-ID",
|
||||||
"appId": "App ID",
|
"appWithIdOrNameNotFound": "Er werd geen app gevonden met dat ID of die naam",
|
||||||
"appWithIdOrNameNotFound": "Er werd geen app gevonden met dat ID of die naam",
|
"reposHaveMultipleApps": "Repositories kunnen meerdere apps bevatten",
|
||||||
"reposHaveMultipleApps": "Repositories kunnen meerdere apps bevatten",
|
"fdroidThirdPartyRepo": "F-Droid Repository van derden",
|
||||||
"fdroidThirdPartyRepo": "F-Droid Third-Party Repo",
|
"steamMobile": "Stoommobiel",
|
||||||
"steam": "Steam",
|
"steamChat": "Steamchat",
|
||||||
"steamMobile": "Steam Mobile",
|
"install": "Installeren",
|
||||||
"steamChat": "Steam Chat",
|
"markInstalled": "Als geïnstalleerd markere",
|
||||||
"install": "Installeren",
|
"update": "Update",
|
||||||
"markInstalled": "Als geïnstalleerd markere",
|
"markUpdated": "Markeren als bijgewerkt",
|
||||||
"update": "Update",
|
"additionalOptions": "Aanvullende opties",
|
||||||
"markUpdated": "Markeren als bijgewerkt",
|
"disableVersionDetection": "Versieherkenning uitschakelen",
|
||||||
"additionalOptions": "Aanvullende opties",
|
"noVersionDetectionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt.",
|
||||||
"disableVersionDetection": "Versieherkenning uitschakelen",
|
"downloadingX": "Downloaden {}",
|
||||||
"noVersionDetectionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt.",
|
"downloadNotifDescription": "Stelt de gebruiker op de hoogte van de voortgang bij het downloaden van een app",
|
||||||
"downloadingX": "Downloaden {}",
|
"noAPKFound": "Geen APK gevonden",
|
||||||
"downloadNotifDescription": "Stelt de gebruiker op de hoogte van de voortgang bij het downloaden van een app",
|
"noVersionDetection": "Geen versieherkenning",
|
||||||
"noAPKFound": "Geen APK gevonden",
|
"categorize": "Categoriseren",
|
||||||
"noVersionDetection": "Geen versieherkenning",
|
"categories": "Categorieën",
|
||||||
"categorize": "Categoriseren",
|
"category": "Categorie",
|
||||||
"categories": "Categorieën",
|
"noCategory": "Geen categorie",
|
||||||
"category": "Categorie",
|
"noCategories": "Geen categorieën",
|
||||||
"noCategory": "Geen categorie",
|
"deleteCategoriesQuestion": "Categorieën verwijderen?",
|
||||||
"noCategories": "Geen categorieën",
|
"categoryDeleteWarning": "Alle apps in verwijderde categorieën worden teruggezet naar 'ongecategoriseerd'.",
|
||||||
"deleteCategoriesQuestion": "Categorieën verwijderen?",
|
"addCategory": "Categorie toevoegen",
|
||||||
"categoryDeleteWarning": "Alle apps in verwijderde categorieën worden teruggezet naar 'ongecategoriseerd'.",
|
"label": "Etiket",
|
||||||
"addCategory": "Categorie toevoegen",
|
"language": "Taal",
|
||||||
"label": "Label",
|
"copiedToClipboard": "Gekopieerd naar klembord",
|
||||||
"language": "Taal",
|
"storagePermissionDenied": "Toegang tot opslag geweigerd",
|
||||||
"copiedToClipboard": "Gekopieerd naar klembord",
|
"selectedCategorizeWarning": "Dit zal eventuele bestaande categorie-instellingen voor de geselecteerde apps vervangen.",
|
||||||
"storagePermissionDenied": "Toegang tot opslag geweigerd",
|
"filterAPKsByRegEx": "Filter APK's op reguliere expressie",
|
||||||
"selectedCategorizeWarning": "Dit zal eventuele bestaande categorie-instellingen voor de geselecteerde apps vervangen.",
|
"removeFromObtainium": "Verwijder van Obtainium",
|
||||||
"filterAPKsByRegEx": "Filter APK's op reguliere expressie",
|
"uninstallFromDevice": "Verwijder van apparaat",
|
||||||
"removeFromObtainium": "Verwijder van Obtainium",
|
"onlyWorksWithNonVersionDetectApps": "Werkt alleen voor apps waarbij versieherkenning is uitgeschakeld.",
|
||||||
"uninstallFromDevice": "Verwijder van apparaat",
|
"releaseDateAsVersion": "Gebruik de releasedatum als versie",
|
||||||
"onlyWorksWithNonVersionDetectApps": "Werkt alleen voor apps waarbij versieherkenning is uitgeschakeld.",
|
"releaseDateAsVersionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt, maar waar wel een releasedatum beschikbaar is.",
|
||||||
"releaseDateAsVersion": "Gebruik de releasedatum als versie",
|
"changes": "Veranderingen",
|
||||||
"releaseDateAsVersionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt, maar waar wel een releasedatum beschikbaar is.",
|
"releaseDate": "Releasedatum",
|
||||||
"changes": "Veranderingen",
|
"importFromURLsInFile": "Importeren vanaf URL's in een bestand (zoals OPML)",
|
||||||
"releaseDate": "Releasedatum",
|
"versionDetectionExplanation": "Versiereeks afstemmen met versie gedetecteerd door besturingssysteem",
|
||||||
"importFromURLsInFile": "Importeren vanaf URL's in een bestand (zoals OPML)",
|
"versionDetection": "Versieherkenning",
|
||||||
"versionDetection": "Versieherkenning",
|
"standardVersionDetection": "Standaard versieherkenning",
|
||||||
"standardVersionDetection": "Standaard versieherkenning",
|
"groupByCategory": "Groepeer op categorie",
|
||||||
"groupByCategory": "Groepeer op categorie",
|
"autoApkFilterByArch": "Poging om APK's te filteren op CPU-architectuur indien mogelijk",
|
||||||
"autoApkFilterByArch": "Poging om APK's te filteren op CPU-architectuur indien mogelijk",
|
"overrideSource": "Bron overschrijven",
|
||||||
"overrideSource": "Bron overschrijven",
|
"dontShowAgain": "Laat dit niet meer zien",
|
||||||
"dontShowAgain": "Don't show this again",
|
"dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven",
|
||||||
"dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven",
|
"dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven",
|
||||||
"dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven",
|
"moveNonInstalledAppsToBottom": "Verplaats niet-geïnstalleerde apps naar de onderkant van de apps-weergave",
|
||||||
"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)",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Maakt het mogelijk beter te zoeken naar APK's)",
|
"about": "Over",
|
||||||
"about": "Over",
|
"requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)",
|
||||||
"requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)",
|
"checkOnStart": "Controleren op updates bij opstarten",
|
||||||
"checkOnStart": "Controleren op updates bij opstarten",
|
"tryInferAppIdFromCode": "Probeer de app-ID af te leiden uit de broncode",
|
||||||
"tryInferAppIdFromCode": "Probeer de app-ID af te leiden uit de broncode",
|
"removeOnExternalUninstall": "Automatisch extern verwijderde apps verwijderen",
|
||||||
"removeOnExternalUninstall": "Automatisch extern verwijderde apps verwijderen",
|
"pickHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
|
||||||
"pickHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
|
"checkUpdateOnDetailPage": "Controleren op updates bij het openen van een app-detailpagina",
|
||||||
"checkUpdateOnDetailPage": "Controleren op updates bij het openen van een app-detailpagina",
|
"disablePageTransitions": "Schakel overgangsanimaties tussen pagina's uit",
|
||||||
"disablePageTransitions": "Schakel overgangsanimaties tussen pagina's uit",
|
"reversePageTransitions": "Omgekeerde overgangsanimaties tussen pagina's",
|
||||||
"reversePageTransitions": "Omgekeerde overgangsanimaties tussen pagina's",
|
"minStarCount": "Minimale Github Stars",
|
||||||
"minStarCount": "Minimale Github Stars",
|
"addInfoBelow": "Voeg deze informatie hieronder toe.",
|
||||||
"addInfoBelow": "Voeg deze informatie hieronder toe.",
|
"addInfoInSettings": "Voeg deze informatie toe in de instellingen.",
|
||||||
"addInfoInSettings": "Voeg deze informatie toe in de instellingen.",
|
"githubSourceNote": "Beperkingen van GitHub kunnen worden vermeden door het gebruik van een API-sleutel.",
|
||||||
"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.",
|
||||||
"gitlabSourceNote": "GitLab APK-extractie werkt mogelijk niet zonder een API-sleutel.",
|
"sortByLastLinkSegment": "Sorteren op alleen het laatste segment van de link",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.",
|
||||||
"filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.",
|
"customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').",
|
||||||
"customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').",
|
"appsPossiblyUpdated": "Poging tot app-updates",
|
||||||
"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",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps mogelijk in de achtergrond zijn toegepast",
|
"xWasPossiblyUpdatedToY": "{} mogelijk bijgewerkt naar {}.",
|
||||||
"xWasPossiblyUpdatedToY": "{} mogelijk bijgewerkt naar {}.",
|
"enableBackgroundUpdates": "Achtergrondupdates inschakelen",
|
||||||
"enableBackgroundUpdates": "Achtergrondupdates inschakelen",
|
"backgroundUpdateReqsExplanation": "Achtergrondupdates zijn mogelijk niet voor alle apps mogelijk.",
|
||||||
"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.",
|
||||||
"backgroundUpdateLimitsExplanation": "Het succes van een installatie in de achtergrond kan alleen worden bepaald wanneer Obtainium is geopend.",
|
"verifyLatestTag": "Verifieer de 'Laatste'-tag",
|
||||||
"verifyLatestTag": "Verifieer de 'Laatste'-tag",
|
"intermediateLinkRegex": "Filter voor een 'Intermediaire' link om te bezoeken",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"filterByLinkText": "Links filteren op linktekst",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"intermediateLinkNotFound": "Tussenliggende link niet gevonden",
|
||||||
"intermediateLinkNotFound": "Tussenliggende link niet gevonden",
|
"intermediateLink": "Intermediaire link",
|
||||||
"intermediateLink": "Intermediate link",
|
"exemptFromBackgroundUpdates": "Vrijgesteld van achtergrondupdates (indien ingeschakeld)",
|
||||||
"exemptFromBackgroundUpdates": "Vrijgesteld van achtergrondupdates (indien ingeschakeld)",
|
"bgUpdatesOnWiFiOnly": "Achtergrondupdates uitschakelen wanneer niet verbonden met WiFi",
|
||||||
"bgUpdatesOnWiFiOnly": "Achtergrondupdates uitschakelen wanneer niet verbonden met WiFi",
|
"autoSelectHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
|
||||||
"autoSelectHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
|
"versionExtractionRegEx": "Reguliere expressie voor versie-extractie",
|
||||||
"versionExtractionRegEx": "Reguliere expressie voor versie-extractie",
|
"matchGroupToUse": "Overeenkomende groep om te gebruiken voor de 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.",
|
||||||
"highlightTouchTargets": "Markeer minder voor de hand liggende aanraakdoelen.",
|
"pickExportDir": "Kies de exportmap",
|
||||||
"pickExportDir": "Kies de exportmap",
|
"autoExportOnChanges": "Automatisch exporteren bij wijzigingen",
|
||||||
"autoExportOnChanges": "Automatisch exporteren bij wijzigingen",
|
"includeSettings": "Instellingen opnemen",
|
||||||
"includeSettings": "Include settings",
|
"filterVersionsByRegEx": "Filter versies met een reguliere expressie",
|
||||||
"filterVersionsByRegEx": "Filter versies met een reguliere expressie",
|
"trySelectingSuggestedVersionCode": "Probeer de voorgestelde versiecode APK te selecteren",
|
||||||
"trySelectingSuggestedVersionCode": "Probeer de voorgestelde versiecode APK te selecteren",
|
"dontSortReleasesList": "Volgorde van releases behouden vanuit de API",
|
||||||
"dontSortReleasesList": "Volgorde van releases behouden vanuit de API",
|
"reverseSort": "Sortering omkeren",
|
||||||
"reverseSort": "Sortering omkeren",
|
"takeFirstLink": "Neem de eerste link",
|
||||||
"takeFirstLink": "Take first link",
|
"skipSort": "Sorteren overslaan",
|
||||||
"skipSort": "Skip sorting",
|
"debugMenu": "Debug menu",
|
||||||
"debugMenu": "Debug menu",
|
"bgTaskStarted": "Achtergrondtaak gestart - controleer de logs.",
|
||||||
"bgTaskStarted": "Achtergrondtaak gestart - controleer de logs.",
|
"runBgCheckNow": "Voer nu een achtergrondupdatecontrole uit",
|
||||||
"runBgCheckNow": "Voer nu een achtergrondupdatecontrole uit",
|
"versionExtractWholePage": "De reguliere expressie voor versie-extractie toepassen op de hele pagina",
|
||||||
"versionExtractWholePage": "De reguliere expressie voor versie-extractie toepassen op de hele pagina",
|
"installing": "Installeren",
|
||||||
"installing": "Installeren",
|
"skipUpdateNotifications": "Updatemeldingen overslaan",
|
||||||
"skipUpdateNotifications": "Updatemeldingen overslaan",
|
"updatesAvailableNotifChannel": "Updates beschikbaar",
|
||||||
"updatesAvailableNotifChannel": "Updates beschikbaar",
|
"appsUpdatedNotifChannel": "Apps bijgewerkt",
|
||||||
"appsUpdatedNotifChannel": "Apps bijgewerkt",
|
"appsPossiblyUpdatedNotifChannel": "Poging tot app-updates",
|
||||||
"appsPossiblyUpdatedNotifChannel": "Poging tot app-updates",
|
"errorCheckingUpdatesNotifChannel": "Foutcontrole bij het zoeken naar updates",
|
||||||
"errorCheckingUpdatesNotifChannel": "Foutcontrole bij het zoeken naar updates",
|
"appsRemovedNotifChannel": "Apps verwijderd",
|
||||||
"appsRemovedNotifChannel": "Apps verwijderd",
|
"downloadingXNotifChannel": "{} downloaden",
|
||||||
"downloadingXNotifChannel": "{} downloaden",
|
"completeAppInstallationNotifChannel": "Voltooien van de app-installatie",
|
||||||
"completeAppInstallationNotifChannel": "Voltooien van de app-installatie",
|
"checkingForUpdatesNotifChannel": "Controleren op updates",
|
||||||
"checkingForUpdatesNotifChannel": "Controleren op updates",
|
"onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde en Track-Only apps controleren op updates",
|
||||||
"onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde en Track-Only apps controleren op updates",
|
"supportFixedAPKURL": "Ondersteuning vaste APK URL's",
|
||||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
"selectX": "Selecteer {}",
|
||||||
"selectX": "Select {}",
|
"parallelDownloads": "Parallelle downloads toestaan",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"installMethod": "Installatiemethode",
|
||||||
"installMethod": "Installation method",
|
"normal": "Normaal",
|
||||||
"normal": "Normal",
|
"root": "Wortel",
|
||||||
"shizuku": "Shizuku",
|
"shizukuBinderNotFound": "Shizuku draait niet",
|
||||||
"root": "Root",
|
"useSystemFont": "Gebruik het systeemlettertype",
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"systemFontError": "Fout bij het laden van het systeemlettertype: {}",
|
||||||
"removeAppQuestion": {
|
"useVersionCodeAsOSVersion": "Gebruik app versieCode als door OS gedetecteerde versie",
|
||||||
"one": "App verwijderen?",
|
"requestHeader": "Verzoekkoptekst",
|
||||||
"other": "Apps verwijderen?"
|
"useLatestAssetDateAsReleaseDate": "Gebruik laatste upload als releasedatum",
|
||||||
},
|
"defaultPseudoVersioningMethod": "Standaard pseudo-versiebeheermethode",
|
||||||
"tooManyRequestsTryAgainInMinutes": {
|
"partialAPKHash": "Gedeeltelijke APK-hash",
|
||||||
"one": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuut",
|
"APKLinkHash": "APK-link-hash",
|
||||||
"other": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuten"
|
"directAPKLink": "Directe APK-link",
|
||||||
},
|
"pseudoVersionInUse": "Er is een pseudo-versie in gebruik",
|
||||||
"bgUpdateGotErrorRetryInMinutes": {
|
"installed": "Geïnstalleerd",
|
||||||
"one": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuut",
|
"latest": "Laatste",
|
||||||
"other": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuten"
|
"invertRegEx": "Reguliere expressie omkeren",
|
||||||
},
|
"note": "Opmerking",
|
||||||
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
"selfHostedNote": "De \"{}\" dropdown kan gebruikt worden om zelf gehoste/aangepaste instanties van elke bron te bereiken.",
|
||||||
"one": "Achtergrondupdatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig",
|
"badDownload": "De APK kon niet worden verwerkt (incompatibele of gedeeltelijke download)",
|
||||||
"other": "Achtergrondupdatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig"
|
"removeAppQuestion": {
|
||||||
},
|
"one": "App verwijderen?",
|
||||||
"apps": {
|
"other": "Apps verwijderen?"
|
||||||
"one": "{} app",
|
},
|
||||||
"other": "{} apps"
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
},
|
"one": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuut",
|
||||||
"url": {
|
"other": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuten"
|
||||||
"one": "{} URL",
|
},
|
||||||
"other": "{} URLs"
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
},
|
"one": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuut",
|
||||||
"minute": {
|
"other": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuten"
|
||||||
"one": "{} minuut",
|
},
|
||||||
"other": "{} minuten"
|
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||||
},
|
"one": "Achtergrondupdatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig",
|
||||||
"hour": {
|
"other": "Achtergrondupdatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig"
|
||||||
"one": "{} uur",
|
},
|
||||||
"other": "{} uur"
|
"apps": {
|
||||||
},
|
"one": "{} app",
|
||||||
"day": {
|
"other": "{} apps"
|
||||||
"one": "{} dag",
|
},
|
||||||
"other": "{} dagen"
|
"url": {
|
||||||
},
|
"one": "{} URL",
|
||||||
"clearedNLogsBeforeXAfterY": {
|
"other": "{} URL's"
|
||||||
"one": "{n} logboekitem gewist (voor = {before}, na = {after})",
|
},
|
||||||
"other": "{n} logboekitems gewist (voor = {before}, na = {after})"
|
"minute": {
|
||||||
},
|
"one": "{} minuut",
|
||||||
"xAndNMoreUpdatesAvailable": {
|
"other": "{} minuten"
|
||||||
"one": "{} en nog 1 app hebben updates.",
|
},
|
||||||
"other": "{} en {} meer apps hebben updates."
|
"hour": {
|
||||||
},
|
"one": "{} uur",
|
||||||
"xAndNMoreUpdatesInstalled": {
|
"other": "{} uur"
|
||||||
"one": "{} en nog 1 app is bijgewerkt.",
|
},
|
||||||
"other": "{} en {} meer apps zijn bijgewerkt."
|
"day": {
|
||||||
},
|
"one": "{} dag",
|
||||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
"other": "{} dagen"
|
||||||
"one": "{} en nog 1 app zijn mogelijk bijgewerkt.",
|
},
|
||||||
"other": "{} en {} meer apps zijn mogelijk bijgwerkt."
|
"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."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"cantInstallOlderVersion": "Nie można zainstalować starszej wersji aplikacji",
|
"cantInstallOlderVersion": "Nie można zainstalować starszej wersji aplikacji",
|
||||||
"appIdMismatch": "Pobrane ID pakietu nie pasuje do istniejącego ID aplikacji",
|
"appIdMismatch": "Pobrane ID pakietu nie pasuje do istniejącego ID aplikacji",
|
||||||
"functionNotImplemented": "Ta klasa nie zaimplementowała tej funkcji",
|
"functionNotImplemented": "Ta klasa nie zaimplementowała tej funkcji",
|
||||||
"placeholder": "Placeholder",
|
"placeholder": "Zbiornik",
|
||||||
"someErrors": "Wystąpiły pewne błędy",
|
"someErrors": "Wystąpiły pewne błędy",
|
||||||
"unexpectedError": "Nieoczekiwany błąd",
|
"unexpectedError": "Nieoczekiwany błąd",
|
||||||
"ok": "Okej",
|
"ok": "Okej",
|
||||||
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Postęp: {}%",
|
"percentProgress": "Postęp: {}%",
|
||||||
"pleaseWait": "Proszę czekać",
|
"pleaseWait": "Proszę czekać",
|
||||||
"updateAvailable": "Dostępna aktualizacja",
|
"updateAvailable": "Dostępna aktualizacja",
|
||||||
"estimateInBracketsShort": "(Szac.)",
|
|
||||||
"notInstalled": "Nie zainstalowano",
|
"notInstalled": "Nie zainstalowano",
|
||||||
"estimateInBrackets": "(Szacunkowo)",
|
"pseudoVersion": "pseudowersja",
|
||||||
"selectAll": "Zaznacz wszystkie",
|
"selectAll": "Zaznacz wszystkie",
|
||||||
"deselectX": "Odznacz {}",
|
"deselectX": "Odznacz {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} zostanie usunięty z Obtainium, ale pozostanie zainstalowany na urządzeniu.",
|
"xWillBeRemovedButRemainInstalled": "{} zostanie usunięty z Obtainium, ale pozostanie zainstalowany na urządzeniu.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Odepnij",
|
"unpinFromTop": "Odepnij",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Zresetować status instalacji dla wybranych aplikacji?",
|
"resetInstallStatusForSelectedAppsQuestion": "Zresetować status instalacji dla wybranych aplikacji?",
|
||||||
"installStatusOfXWillBeResetExplanation": "Stan instalacji wybranych aplikacji zostanie zresetowany.\n\nMoże być to pomocne, gdy wersja aplikacji wyświetlana w Obtainium jest nieprawidłowa z powodu nieudanych aktualizacji lub innych problemów.",
|
"installStatusOfXWillBeResetExplanation": "Stan instalacji wybranych aplikacji zostanie zresetowany.\n\nMoże być to pomocne, gdy wersja aplikacji wyświetlana w Obtainium jest nieprawidłowa z powodu nieudanych aktualizacji lub innych problemów.",
|
||||||
|
"customLinkMessage": "Te linki działają na urządzeniach z zainstalowanym Obtainium",
|
||||||
|
"shareAppConfigLinks": "Udostępnij konfigurację aplikacji jako link HTML",
|
||||||
"shareSelectedAppURLs": "Udostępnij wybrane adresy URL aplikacji",
|
"shareSelectedAppURLs": "Udostępnij wybrane adresy URL aplikacji",
|
||||||
"resetInstallStatus": "Zresetuj stan instalacji",
|
"resetInstallStatus": "Zresetuj stan instalacji",
|
||||||
"more": "Więcej",
|
"more": "Więcej",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Ciemny",
|
"dark": "Ciemny",
|
||||||
"light": "Jasny",
|
"light": "Jasny",
|
||||||
"followSystem": "Zgodny z systemem",
|
"followSystem": "Zgodny z systemem",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Użyj czarnego motywu",
|
"useBlackTheme": "Użyj czarnego motywu",
|
||||||
"appSortBy": "Sortuj aplikacje według",
|
"appSortBy": "Sortuj aplikacje według",
|
||||||
"authorName": "Autor/Nazwa",
|
"authorName": "Autor/Nazwa",
|
||||||
@ -175,9 +174,8 @@
|
|||||||
"appWithIdOrNameNotFound": "Nie znaleziono aplikacji o tym identyfikatorze lub nazwie",
|
"appWithIdOrNameNotFound": "Nie znaleziono aplikacji o tym identyfikatorze lub nazwie",
|
||||||
"reposHaveMultipleApps": "Repozytoria mogą zawierać wiele aplikacji",
|
"reposHaveMultipleApps": "Repozytoria mogą zawierać wiele aplikacji",
|
||||||
"fdroidThirdPartyRepo": "Zewnętrzne repo F-Droid",
|
"fdroidThirdPartyRepo": "Zewnętrzne repo F-Droid",
|
||||||
"steam": "Steam",
|
|
||||||
"steamMobile": "Mobilny Steam",
|
"steamMobile": "Mobilny Steam",
|
||||||
"steamChat": "Steam Chat",
|
"steamChat": "Czat Steam",
|
||||||
"install": "Instaluj",
|
"install": "Instaluj",
|
||||||
"markInstalled": "Oznacz jako zainstalowane",
|
"markInstalled": "Oznacz jako zainstalowane",
|
||||||
"update": "Zaktualizuj",
|
"update": "Zaktualizuj",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Zmiany",
|
"changes": "Zmiany",
|
||||||
"releaseDate": "Data wydania",
|
"releaseDate": "Data wydania",
|
||||||
"importFromURLsInFile": "Importuj z adresów URL w pliku (typu OPML)",
|
"importFromURLsInFile": "Importuj z adresów URL w pliku (typu OPML)",
|
||||||
|
"versionDetectionExplanation": "Uzgodnij ciąg wersji z wersją wykrytą w systemie operacyjnym",
|
||||||
"versionDetection": "Wykrywanie wersji",
|
"versionDetection": "Wykrywanie wersji",
|
||||||
"standardVersionDetection": "Standardowe wykrywanie wersji",
|
"standardVersionDetection": "Standardowe wykrywanie wersji",
|
||||||
"groupByCategory": "Grupuj według kategorii",
|
"groupByCategory": "Grupuj według kategorii",
|
||||||
@ -235,7 +234,7 @@
|
|||||||
"addInfoInSettings": "Dodaj tę informację w Ustawieniach.",
|
"addInfoInSettings": "Dodaj tę informację w Ustawieniach.",
|
||||||
"githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.",
|
"githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.",
|
||||||
"gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.",
|
"gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Sortuj tylko według ostatniego segmentu łącza",
|
||||||
"filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego",
|
"filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego",
|
||||||
"customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")",
|
"customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")",
|
||||||
"appsPossiblyUpdated": "Aplikacje mogły zostać zaktualizowane",
|
"appsPossiblyUpdated": "Aplikacje mogły zostać zaktualizowane",
|
||||||
@ -245,10 +244,10 @@
|
|||||||
"backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.",
|
"backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.",
|
||||||
"backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.",
|
"backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.",
|
||||||
"verifyLatestTag": "Zweryfikuj najnowszy tag",
|
"verifyLatestTag": "Zweryfikuj najnowszy tag",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Filtruj link \"pośredni\" do odwiedzenia",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Filtruj linki według tekstu linku",
|
||||||
"intermediateLinkNotFound": "Nie znaleziono linku pośredniego",
|
"intermediateLinkNotFound": "Nie znaleziono linku pośredniego",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Łącze pośrednie",
|
||||||
"exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)",
|
"exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)",
|
||||||
"bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi",
|
"bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi",
|
||||||
"autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK",
|
"autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK",
|
||||||
@ -257,13 +256,13 @@
|
|||||||
"highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe",
|
"highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe",
|
||||||
"pickExportDir": "Wybierz katalog eksportu",
|
"pickExportDir": "Wybierz katalog eksportu",
|
||||||
"autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian",
|
"autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Dołącz ustawienia",
|
||||||
"filterVersionsByRegEx": "Filtruj wersje według wyrażenia regularnego",
|
"filterVersionsByRegEx": "Filtruj wersje według wyrażenia regularnego",
|
||||||
"trySelectingSuggestedVersionCode": "Spróbuj wybierać sugerowany kod wersji APK",
|
"trySelectingSuggestedVersionCode": "Spróbuj wybierać sugerowany kod wersji APK",
|
||||||
"dontSortReleasesList": "Utrzymaj kolejność wydań z interfejsu API",
|
"dontSortReleasesList": "Utrzymaj kolejność wydań z interfejsu API",
|
||||||
"reverseSort": "Odwrotne sortowanie",
|
"reverseSort": "Odwrotne sortowanie",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Weź pierwszy link",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Pomiń sortowanie",
|
||||||
"debugMenu": "Menu debugowania",
|
"debugMenu": "Menu debugowania",
|
||||||
"bgTaskStarted": "Uruchomiono zadanie w tle - sprawdź logi.",
|
"bgTaskStarted": "Uruchomiono zadanie w tle - sprawdź logi.",
|
||||||
"runBgCheckNow": "Wymuś sprawdzenie aktualizacji w tle",
|
"runBgCheckNow": "Wymuś sprawdzenie aktualizacji w tle",
|
||||||
@ -281,12 +280,27 @@
|
|||||||
"onlyCheckInstalledOrTrackOnlyApps": "Sprawdzaj tylko zainstalowane i obserwowane aplikacje pod kątem aktualizacji",
|
"onlyCheckInstalledOrTrackOnlyApps": "Sprawdzaj tylko zainstalowane i obserwowane aplikacje pod kątem aktualizacji",
|
||||||
"supportFixedAPKURL": "Obsługuj stałe adresy URL APK",
|
"supportFixedAPKURL": "Obsługuj stałe adresy URL APK",
|
||||||
"selectX": "Wybierz {}",
|
"selectX": "Wybierz {}",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "Zezwól na pobieranie równoległe",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "Metoda instalacji",
|
||||||
"normal": "Normal",
|
"normal": "Normalna",
|
||||||
"shizuku": "Shizuku",
|
"root": "Źródło",
|
||||||
"root": "Root",
|
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"shizukuBinderNotFound": "Shizuku is not running",
|
||||||
|
"useSystemFont": "Użyj czcionki systemowej",
|
||||||
|
"systemFontError": "Błąd podczas ładowania czcionki systemowej: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Użyj kodu wersji aplikacji jako wersji wykrytej przez system operacyjny",
|
||||||
|
"requestHeader": "Nagłówek żądania",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Użyj najnowszego przesłanego zasobu jako daty wydania",
|
||||||
|
"defaultPseudoVersioningMethod": "Domyślna metoda pseudowersji",
|
||||||
|
"partialAPKHash": "Częściowy skrót APK",
|
||||||
|
"APKLinkHash": "Skrót łącza APK",
|
||||||
|
"directAPKLink": "Bezpośredni link APK",
|
||||||
|
"pseudoVersionInUse": "Pseudowersja jest w użyciu",
|
||||||
|
"installed": "Zainstalowano",
|
||||||
|
"latest": "Najnowszy",
|
||||||
|
"invertRegEx": "Odwróć wyrażenie regularne",
|
||||||
|
"note": "Uwaga",
|
||||||
|
"selfHostedNote": "Lista rozwijana \"{}\" może być używana do uzyskiwania dostępu do samodzielnie hostowanych / niestandardowych instancji dowolnego źródła.",
|
||||||
|
"badDownload": "Nie można przeanalizować pliku APK (niekompatybilny lub częściowo pobrany).",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Usunąć aplikację?",
|
"one": "Usunąć aplikację?",
|
||||||
"few": "Usunąć aplikacje?",
|
"few": "Usunąć aplikacje?",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"invalidURLForSource": "URL {} inválida",
|
"invalidURLForSource": "URL {} inválida",
|
||||||
"noReleaseFound": "Não foi possível encontrar uma versão adequada",
|
"noReleaseFound": "Não foi possível encontrar uma versão adequada",
|
||||||
"noVersionFound": "Não foi possível encontrar uma versão",
|
"noVersionFound": "Não foi possível encontrar uma versão",
|
||||||
"urlMatchesNoSource": "URL não corresponde a uma fonte conhecida",
|
"urlMatchesNoSource": "A URL não corresponde a uma fonte conhecida",
|
||||||
"cantInstallOlderVersion": "Não é permitido instalar uma versão anterior de um aplicativo",
|
"cantInstallOlderVersion": "Não é permitido instalar uma versão anterior de um aplicativo",
|
||||||
"appIdMismatch": "ID do pacote baixado não é igual ao ID do aplicativo instalado",
|
"appIdMismatch": "ID do pacote baixado não é igual ao ID do aplicativo instalado",
|
||||||
"functionNotImplemented": "Esta classe não implementou essa função",
|
"functionNotImplemented": "Esta classe não implementou essa função",
|
||||||
@ -11,10 +11,10 @@
|
|||||||
"unexpectedError": "Erro inesperado",
|
"unexpectedError": "Erro inesperado",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"and": "e",
|
"and": "e",
|
||||||
"githubPATLabel": "Token de acesso pessoal do GitHub (Reduz tempos de espera)",
|
"githubPATLabel": "Token de acesso pessoal do GitHub\n(Reduz tempos de espera)",
|
||||||
"includePrereleases": "Incluir pré-lançamentos",
|
"includePrereleases": "Incluir pré-lançamentos",
|
||||||
"fallbackToOlderReleases": "Retornar para versões anteriores",
|
"fallbackToOlderReleases": "Retornar para versões anteriores",
|
||||||
"filterReleaseTitlesByRegEx": "Filtrar títulos de versões por expressão regular",
|
"filterReleaseTitlesByRegEx": "Filtrar títulos de versões usando expressão regular",
|
||||||
"invalidRegEx": "Expressão regular inválida",
|
"invalidRegEx": "Expressão regular inválida",
|
||||||
"noDescription": "Sem descrição",
|
"noDescription": "Sem descrição",
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
@ -22,7 +22,7 @@
|
|||||||
"requiredInBrackets": "(Necessário)",
|
"requiredInBrackets": "(Necessário)",
|
||||||
"dropdownNoOptsError": "ERRO: O DROPDOWN DEVE TER PELO MENOS UMA OPÇÃO",
|
"dropdownNoOptsError": "ERRO: O DROPDOWN DEVE TER PELO MENOS UMA OPÇÃO",
|
||||||
"colour": "Cor",
|
"colour": "Cor",
|
||||||
"githubStarredRepos": "Favoritados no GitHub",
|
"githubStarredRepos": "repositórios favoritos no GitHub",
|
||||||
"uname": "Nome de usuário",
|
"uname": "Nome de usuário",
|
||||||
"wrongArgNum": "Número de argumentos errado",
|
"wrongArgNum": "Número de argumentos errado",
|
||||||
"xIsTrackOnly": "{} é 'Apenas monitorar'",
|
"xIsTrackOnly": "{} é 'Apenas monitorar'",
|
||||||
@ -38,12 +38,12 @@
|
|||||||
"appSourceURL": "URL de origem do aplicativo",
|
"appSourceURL": "URL de origem do aplicativo",
|
||||||
"error": "Erro",
|
"error": "Erro",
|
||||||
"add": "Adicionar",
|
"add": "Adicionar",
|
||||||
"searchSomeSourcesLabel": "Procurar (Apenas algumas fontes)",
|
"searchSomeSourcesLabel": "Procurar (apenas algumas fontes)",
|
||||||
"search": "Procurar",
|
"search": "Procurar",
|
||||||
"additionalOptsFor": "Opções adicionais para {}",
|
"additionalOptsFor": "Opções adicionais para {}",
|
||||||
"supportedSources": "Fontes compatíveis",
|
"supportedSources": "Fontes compatíveis",
|
||||||
"trackOnlyInBrackets": "(Apenas monitorar)",
|
"trackOnlyInBrackets": "(apenas monitorar)",
|
||||||
"searchableInBrackets": "(Pesquisável)",
|
"searchableInBrackets": "(pesquisável)",
|
||||||
"appsString": "Aplicativos",
|
"appsString": "Aplicativos",
|
||||||
"noApps": "Não há aplicativos",
|
"noApps": "Não há aplicativos",
|
||||||
"noAppsForFilter": "Sem aplicativos para filtrar",
|
"noAppsForFilter": "Sem aplicativos para filtrar",
|
||||||
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Progresso: {}%",
|
"percentProgress": "Progresso: {}%",
|
||||||
"pleaseWait": "Por favor, espere",
|
"pleaseWait": "Por favor, espere",
|
||||||
"updateAvailable": "Atualização disponível",
|
"updateAvailable": "Atualização disponível",
|
||||||
"estimateInBracketsShort": "(Aprox.)",
|
|
||||||
"notInstalled": "Não instalado",
|
"notInstalled": "Não instalado",
|
||||||
"estimateInBrackets": "(Aproximado)",
|
"pseudoVersion": "pseudo-versão",
|
||||||
"selectAll": "Selecionar todos",
|
"selectAll": "Selecionar todos",
|
||||||
"deselectX": "Deselecionar {}",
|
"deselectX": "Deselecionar {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} será removido do Obtainium mais permanecerá instalado no dispositivo.",
|
"xWillBeRemovedButRemainInstalled": "{} será removido do Obtainium mais permanecerá instalado no dispositivo.",
|
||||||
@ -71,10 +70,12 @@
|
|||||||
"markSelectedAppsUpdated": "Marcar aplicativos selecionados como Atualizados",
|
"markSelectedAppsUpdated": "Marcar aplicativos selecionados como Atualizados",
|
||||||
"pinToTop": "Fixar no topo",
|
"pinToTop": "Fixar no topo",
|
||||||
"unpinFromTop": "Desafixar do topo",
|
"unpinFromTop": "Desafixar do topo",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Reiniciar status de instalação para aplicativos selecionados?",
|
"resetInstallStatusForSelectedAppsQuestion": "Reiniciar status de instalação nos aplicativos selecionados?",
|
||||||
"installStatusOfXWillBeResetExplanation": "O status de instalação de qualquer aplicativo selecionado será reiniciado.\n\nIsso pode ajudar quando uma versão de um aplicativo mostrada no Obtainium é incorreta devido a falhas ao atualizar ou outros problemas.",
|
"installStatusOfXWillBeResetExplanation": "O status de instalação de todos os aplicativos selecionados será reiniciado.\n\nIsso pode ajudar quando uma versão de um aplicativo mostrada no Obtainium é incorreta devido a falhas ao atualizar ou outros problemas.",
|
||||||
|
"customLinkMessage": "Esses links funcionam em dispositivos com o Obtainium instalado",
|
||||||
|
"shareAppConfigLinks": "Compartilhar configuração do aplicativo como link HTML",
|
||||||
"shareSelectedAppURLs": "Compartilhar URLs de aplicativos selecionados",
|
"shareSelectedAppURLs": "Compartilhar URLs de aplicativos selecionados",
|
||||||
"resetInstallStatus": "Reiniciar status de Iistalação",
|
"resetInstallStatus": "Reiniciar status de instalação",
|
||||||
"more": "Mais",
|
"more": "Mais",
|
||||||
"removeOutdatedFilter": "Remover filtro de aplicativos desatualizados",
|
"removeOutdatedFilter": "Remover filtro de aplicativos desatualizados",
|
||||||
"showOutdatedOnly": "Mostrar apenas aplicativos desatualizados",
|
"showOutdatedOnly": "Mostrar apenas aplicativos desatualizados",
|
||||||
@ -83,20 +84,20 @@
|
|||||||
"filterApps": "Filtrar aplicativos",
|
"filterApps": "Filtrar aplicativos",
|
||||||
"appName": "Nome do aplicativo",
|
"appName": "Nome do aplicativo",
|
||||||
"author": "Autor",
|
"author": "Autor",
|
||||||
"upToDateApps": "Aplicativos tualizados",
|
"upToDateApps": "Aplicativos atualizados",
|
||||||
"nonInstalledApps": "Aplicativos não instalados",
|
"nonInstalledApps": "Aplicativos não instalados",
|
||||||
"importExport": "Importar/Exportar",
|
"importExport": "Importar/Exportar",
|
||||||
"settings": "Configurações",
|
"settings": "Configurações",
|
||||||
"exportedTo": "Exportado para {}",
|
"exportedTo": "Exportado para {}",
|
||||||
"obtainiumExport": "Exportar Obtainium",
|
"obtainiumExport": "Exportar dados do Obtainium",
|
||||||
"invalidInput": "Input Inválido",
|
"invalidInput": "Entrada inválida",
|
||||||
"importedX": "Importado {}",
|
"importedX": "Importado {}",
|
||||||
"obtainiumImport": "Importar Obtainium",
|
"obtainiumImport": "Importar dados do Obtainium",
|
||||||
"importFromURLList": "Importar de lista de URLs",
|
"importFromURLList": "Importar de lista de URLs",
|
||||||
"searchQuery": "Pesquisa",
|
"searchQuery": "Pesquisa",
|
||||||
"appURLList": "Lista de URLs de aplicativos",
|
"appURLList": "Lista de URLs de aplicativos",
|
||||||
"line": "Linha",
|
"line": "Linha",
|
||||||
"searchX": "Pesquisa {}",
|
"searchX": "Pesquisar na/o {}",
|
||||||
"noResults": "Nenhum resultado encontrado",
|
"noResults": "Nenhum resultado encontrado",
|
||||||
"importX": "Importar {}",
|
"importX": "Importar {}",
|
||||||
"importedAppsIdDisclaimer": "Aplicativos Importados podem ser mostrados incorretamente como \"Não Instalado\".\nPara consertar, reinstale-os usando o Obtainium.\nIsso não deve afetar dados do aplicativo.\n\nAfeta apenas métodos de importação de URL e de terceiros.",
|
"importedAppsIdDisclaimer": "Aplicativos Importados podem ser mostrados incorretamente como \"Não Instalado\".\nPara consertar, reinstale-os usando o Obtainium.\nIsso não deve afetar dados do aplicativo.\n\nAfeta apenas métodos de importação de URL e de terceiros.",
|
||||||
@ -109,10 +110,8 @@
|
|||||||
"theme": "Tema",
|
"theme": "Tema",
|
||||||
"dark": "Escuro",
|
"dark": "Escuro",
|
||||||
"light": "Claro",
|
"light": "Claro",
|
||||||
"followSystem": "Seguir o sistema",
|
"followSystem": "Padrão do sistema",
|
||||||
"obtainium": "Obtainium",
|
"useBlackTheme": "Usar tema preto AMOLED",
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Usar tema preto completamente escuro",
|
|
||||||
"appSortBy": "Classificar aplicativo por",
|
"appSortBy": "Classificar aplicativo por",
|
||||||
"authorName": "Autor/Nome",
|
"authorName": "Autor/Nome",
|
||||||
"nameAuthor": "Nome/Autor",
|
"nameAuthor": "Nome/Autor",
|
||||||
@ -123,17 +122,17 @@
|
|||||||
"bgUpdateCheckInterval": "Intervalo de verificação de atualizações em segundo-plano",
|
"bgUpdateCheckInterval": "Intervalo de verificação de atualizações em segundo-plano",
|
||||||
"neverManualOnly": "Nunca - apenas manual",
|
"neverManualOnly": "Nunca - apenas manual",
|
||||||
"appearance": "Aparência",
|
"appearance": "Aparência",
|
||||||
"showWebInAppView": "Mostrar página da internet em informações do aplicativo",
|
"showWebInAppView": "Mostrar página web do aplicativo em informações do aplicativo",
|
||||||
"pinUpdates": "Fixar atualizações no topo da janela de aplicativos",
|
"pinUpdates": "Fixar atualizações no topo da janela de aplicativos",
|
||||||
"updates": "Atualizações",
|
"updates": "Atualizações",
|
||||||
"sourceSpecific": "Específico a fonte",
|
"sourceSpecific": "Token de acesso",
|
||||||
"appSource": "Fonte do aplicativo",
|
"appSource": "Fonte do aplicativo",
|
||||||
"noLogs": "Sem logs",
|
"noLogs": "Sem logs",
|
||||||
"appLogs": "Logs do aplicativo",
|
"appLogs": "Logs do aplicativo",
|
||||||
"close": "Fechar",
|
"close": "Fechar",
|
||||||
"share": "Compartilhar",
|
"share": "Compartilhar",
|
||||||
"appNotFound": "Aplicativo não encontrado",
|
"appNotFound": "Aplicativo não encontrado",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"obtainiumExportHyphenatedLowercase": "exportação de obtainium",
|
||||||
"pickAnAPK": "Selecionar um APK",
|
"pickAnAPK": "Selecionar um APK",
|
||||||
"appHasMoreThanOnePackage": "{} tem mais de um pacote:",
|
"appHasMoreThanOnePackage": "{} tem mais de um pacote:",
|
||||||
"deviceSupportsXArch": "Seu dispositivo suporta a arquitetura de CPU {}.",
|
"deviceSupportsXArch": "Seu dispositivo suporta a arquitetura de CPU {}.",
|
||||||
@ -152,7 +151,7 @@
|
|||||||
"appsRemoved": "Aplicativos removidos",
|
"appsRemoved": "Aplicativos removidos",
|
||||||
"appsRemovedNotifDescription": "Notifica o usuário quando um ou mais aplicativos foram removidos devido a erros de carregamento",
|
"appsRemovedNotifDescription": "Notifica o usuário quando um ou mais aplicativos foram removidos devido a erros de carregamento",
|
||||||
"xWasRemovedDueToErrorY": "{} foi removido devido a este erro: {}",
|
"xWasRemovedDueToErrorY": "{} foi removido devido a este erro: {}",
|
||||||
"completeAppInstallation": "Instalação do aplicativo completa",
|
"completeAppInstallation": "Instalação do aplicativo concluída",
|
||||||
"obtainiumMustBeOpenToInstallApps": "Obtainium deve estar aberto para instalar os aplicativos",
|
"obtainiumMustBeOpenToInstallApps": "Obtainium deve estar aberto para instalar os aplicativos",
|
||||||
"completeAppInstallationNotifDescription": "Pede ao usuário que retorne ao Obtainium para finalizar a instalação de um aplicativo",
|
"completeAppInstallationNotifDescription": "Pede ao usuário que retorne ao Obtainium para finalizar a instalação de um aplicativo",
|
||||||
"checkingForUpdates": "Verificando atualizações",
|
"checkingForUpdates": "Verificando atualizações",
|
||||||
@ -168,16 +167,15 @@
|
|||||||
"installedVersionX": "Versão instalada: {}",
|
"installedVersionX": "Versão instalada: {}",
|
||||||
"lastUpdateCheckX": "Última verificação de atualizações: {}",
|
"lastUpdateCheckX": "Última verificação de atualizações: {}",
|
||||||
"remove": "Remover",
|
"remove": "Remover",
|
||||||
"yesMarkUpdated": "Sim, marcar como Atualizado",
|
"yesMarkUpdated": "Sim, marcar como atualizado",
|
||||||
"fdroid": "F-Droid Official",
|
"fdroid": "Oficial F-Droid",
|
||||||
"appIdOrName": "ID do aplicativo ou nome",
|
"appIdOrName": "ID do aplicativo ou nome",
|
||||||
"appId": "ID do aplicativo",
|
"appId": "ID do aplicativo",
|
||||||
"appWithIdOrNameNotFound": "Nenhum aplicativo foi encontrado com esse ID ou nome",
|
"appWithIdOrNameNotFound": "Nenhum aplicativo foi encontrado com esse ID ou nome",
|
||||||
"reposHaveMultipleApps": "Repositórios podem conter multiplos aplicativos",
|
"reposHaveMultipleApps": "Repositórios podem conter múltiplos aplicativos",
|
||||||
"fdroidThirdPartyRepo": "Repositórios de terceiros F-Droid",
|
"fdroidThirdPartyRepo": "Repositórios de terceiros F-Droid",
|
||||||
"steam": "Steam",
|
"steamMobile": "Steam para celular",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "Chat do Steam",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "Instalar",
|
"install": "Instalar",
|
||||||
"markInstalled": "Marcar instalado",
|
"markInstalled": "Marcar instalado",
|
||||||
"update": "Atualizar",
|
"update": "Atualizar",
|
||||||
@ -193,7 +191,7 @@
|
|||||||
"categories": "Categorias",
|
"categories": "Categorias",
|
||||||
"category": "Categoria",
|
"category": "Categoria",
|
||||||
"noCategory": "Sem categoria",
|
"noCategory": "Sem categoria",
|
||||||
"noCategories": "Sem categoria",
|
"noCategories": "Sem categorias",
|
||||||
"deleteCategoriesQuestion": "Deletar categorias?",
|
"deleteCategoriesQuestion": "Deletar categorias?",
|
||||||
"categoryDeleteWarning": "Todos os aplicativos em categorias removidas serão descategorizados.",
|
"categoryDeleteWarning": "Todos os aplicativos em categorias removidas serão descategorizados.",
|
||||||
"addCategory": "Adicionar categoria",
|
"addCategory": "Adicionar categoria",
|
||||||
@ -202,98 +200,113 @@
|
|||||||
"copiedToClipboard": "Copiado para a área de transferência",
|
"copiedToClipboard": "Copiado para a área de transferência",
|
||||||
"storagePermissionDenied": "Permissão de armazenamento negada",
|
"storagePermissionDenied": "Permissão de armazenamento negada",
|
||||||
"selectedCategorizeWarning": "Isso vai substituir qualquer configuração de categoria para os aplicativos selecionados.",
|
"selectedCategorizeWarning": "Isso vai substituir qualquer configuração de categoria para os aplicativos selecionados.",
|
||||||
"filterAPKsByRegEx": "Filtrar APKs por expressão regular",
|
"filterAPKsByRegEx": "Filtrar APKs usando expressão regular",
|
||||||
"removeFromObtainium": "Remover do Obtainium",
|
"removeFromObtainium": "Remover do Obtainium",
|
||||||
"uninstallFromDevice": "Desinstalar do dispositivo",
|
"uninstallFromDevice": "Desinstalar do dispositivo",
|
||||||
"onlyWorksWithNonVersionDetectApps": "Apenas funciona para aplicativos com detecção de versão desativada.",
|
"onlyWorksWithNonVersionDetectApps": "Apenas funciona para aplicativos com detecção de versão desativada.",
|
||||||
"releaseDateAsVersion": "Usar data de lançamento como versão",
|
"releaseDateAsVersion": "Usar data de lançamento como versão",
|
||||||
"releaseDateAsVersionExplanation": "Esta opção só deve ser usada para aplicativos onde a detecção de versão não funciona corretamente, mas há uma data de lançamento disponível.",
|
"releaseDateAsVersionExplanation": "Esta opção só deve ser usada para aplicativos onde a detecção de versão não funciona corretamente, mas há uma data de lançamento disponível.",
|
||||||
"changes": "Mudanças",
|
"changes": "Alterações",
|
||||||
"releaseDate": "Data de lançamento",
|
"releaseDate": "Data de lançamento",
|
||||||
"importFromURLsInFile": "Importar de URLs em arquivo (como OPML)",
|
"importFromURLsInFile": "Importar de URLs em arquivo (formato OPML)",
|
||||||
"versionDetection": "Detecção de Versão",
|
"versionDetectionExplanation": "Reconciliar string de versão com versão detectada no sistema operacional",
|
||||||
|
"versionDetection": "Detecção de versão",
|
||||||
"standardVersionDetection": "Detecção de versão padrão",
|
"standardVersionDetection": "Detecção de versão padrão",
|
||||||
"groupByCategory": "Agroupar por categoria",
|
"groupByCategory": "Agroupar por categoria",
|
||||||
"autoApkFilterByArch": "Tente filtrar APKs por arquitetura de CPU, se possível",
|
"autoApkFilterByArch": "Tente filtrar APKs por arquitetura de CPU, se possível",
|
||||||
"overrideSource": "Substituir fonte",
|
"overrideSource": "Substituir fonte",
|
||||||
"dontShowAgain": "Não mostrar isso novamente",
|
"dontShowAgain": "Não mostrar isso novamente",
|
||||||
"dontShowTrackOnlyWarnings": "Não mostrar avisos 'Apenas Monitorar'",
|
"dontShowTrackOnlyWarnings": "Não mostrar avisos 'Apenas monitorar'",
|
||||||
"dontShowAPKOriginWarnings": "Não mostrar avisos de origem da APK",
|
"dontShowAPKOriginWarnings": "Não mostrar avisos de origem da APK",
|
||||||
"moveNonInstalledAppsToBottom": "Mover aplicativos não instalados para o fundo da lista de aplicativos",
|
"moveNonInstalledAppsToBottom": "Mover aplicativos não instalados para o fundo da lista de aplicativos",
|
||||||
AQUI
|
"gitlabPATLabel": "Token de acesso pessoal do Gitlab\n(Ativa pesquisa e melhora a descoberta de APKs)",
|
||||||
"gitlabPATLabel": "Token de Acceso Pessoal do Gitlab\n(Ativa Pesquisa e Melhor Descoberta de APKs)",
|
|
||||||
"about": "Sobre",
|
"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 ",
|
"checkOnStart": "Verificar se há atualizações ao iniciar",
|
||||||
"tryInferAppIdFromCode": "Tente inferir o ID do aplicativo pelo código-fonte",
|
"tryInferAppIdFromCode": "Tente inferir o ID do aplicativo pelo código-fonte",
|
||||||
"removeOnExternalUninstall": "Remover automaticamente aplicativos desinstalados externamente",
|
"removeOnExternalUninstall": "Remover automaticamente aplicativos desinstalados externamente",
|
||||||
"pickHighestVersionCode": "Auto-selecionar o maior numero de versão do APK",
|
"pickHighestVersionCode": "Auto-selecionar o maior número de versão do APK",
|
||||||
"checkUpdateOnDetailPage": "Checar por atualizações ao abrir a página de detalhes de um aplicativo",
|
"checkUpdateOnDetailPage": "Checar por atualizações ao abrir a página de detalhes de um aplicativo",
|
||||||
"disablePageTransitions": "Desativar animações de transição de pagina",
|
"disablePageTransitions": "Desativar animações de transição de página",
|
||||||
"reversePageTransitions": "Reverter animações de transição de pagina",
|
"reversePageTransitions": "Animações de transição de página invertidas",
|
||||||
"minStarCount": "Contagem Minima de Estrelas",
|
"minStarCount": "Contagem mínima de estrelas",
|
||||||
"addInfoBelow": "Adicionar essa informação abaixo.",
|
"addInfoBelow": "Adicionar essa informação abaixo.",
|
||||||
"addInfoInSettings": "Adicionar essa informação nas configurações.",
|
"addInfoInSettings": "Adicionar essa informação nas configurações.",
|
||||||
"githubSourceNote": "A limitação de taxa do GitHub pode ser evitada usando uma chave de API.",
|
"githubSourceNote": "A limitação de taxa do GitHub pode ser evitada usando uma chave de API.",
|
||||||
"gitlabSourceNote": "A extração de APK do GitLab pode não funcionar sem uma chave de API.",
|
"gitlabSourceNote": "A extração de endereço de download do APK no GitLab provavelmente não funcione sem que seja fornecido uma chave de API.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Ordenar apenas usando o último segmento do link",
|
||||||
"filterReleaseNotesByRegEx": "Filtrar Notas de Lançamento por Expressão Regular",
|
"filterReleaseNotesByRegEx": "Filtrar notas de versão usando Regex",
|
||||||
"customLinkFilterRegex": "Filtro de Link Personalizado por Expressão Regular (Padrão '.apk$')",
|
"customLinkFilterRegex": "Filtro de link personalizado usando expressão regular (Padrão '.apk$')",
|
||||||
"appsPossiblyUpdated": "Tentativas de atualização de aplicativos",
|
"appsPossiblyUpdated": "Tentativas de atualização de aplicativos",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Notifica o usuário de que atualizações de um ou mais aplicativos foram potencialmente aplicadas em segundo-plano",
|
"appsPossiblyUpdatedNotifDescription": "Notifica o usuário de que atualizações de um ou mais aplicativos foram potencialmente aplicadas em segundo-plano",
|
||||||
"xWasPossiblyUpdatedToY": "{} pode ter sido atualizado para {}.",
|
"xWasPossiblyUpdatedToY": "{} pode ter sido atualizado para {}.",
|
||||||
"enableBackgroundUpdates": "Ativar atualizações em segundo-plano",
|
"enableBackgroundUpdates": "Ativar atualizações em segundo-plano",
|
||||||
"backgroundUpdateReqsExplanation": "Atualizações em segundo-plano podem não ser possíveis para todos os aplicativos.",
|
"backgroundUpdateReqsExplanation": "Atualizações em segundo-plano podem não ser possíveis para todos os aplicativos.",
|
||||||
"backgroundUpdateLimitsExplanation": "O sucesso de uma instalação em segundo-plano só pode ser determinado quando o Obtainium é aberto.",
|
"backgroundUpdateLimitsExplanation": "O sucesso de uma instalação em segundo-plano só pode ser determinado quando o Obtainium é aberto.",
|
||||||
"verifyLatestTag": "Verifique a 'ultima' etiqueta",
|
"verifyLatestTag": "Verifique a 'última' etiqueta",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Filtrar um link 'intermediário' para visitar",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Filtrar links pelo texto do link",
|
||||||
"intermediateLinkNotFound": "Link intermediário não encontrado",
|
"intermediateLinkNotFound": "Link intermediário não encontrado",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Link intermediário",
|
||||||
"exemptFromBackgroundUpdates": "Isento de atualizações em segundo-plano (se ativadas)",
|
"exemptFromBackgroundUpdates": "Isento de atualizações em segundo-plano (se ativadas)",
|
||||||
"bgUpdatesOnWiFiOnly": "Desative atualizações em segundo-plano quando não estiver em WiFi",
|
"bgUpdatesOnWiFiOnly": "Desative as atualizações em segundo-plano quando não estiver conectado no Wi-Fi",
|
||||||
"autoSelectHighestVersionCode": "Auto-selecionar o maior codigo de versão",
|
"autoSelectHighestVersionCode": "Auto-selecionar a versão mais recente",
|
||||||
"versionExtractionRegEx": "RegEx para Extração de Versão",
|
"versionExtractionRegEx": "Regex de extração de versão",
|
||||||
"matchGroupToUse": "Grupo de Seleção para Usar",
|
"matchGroupToUse": "Grupo correspondente a ser usado no Regex de extração de versão",
|
||||||
"highlightTouchTargets": "Destaque areas de toque menos óbvias",
|
"highlightTouchTargets": "Realçar áreas sensíveis ao toque que são menos óbvias",
|
||||||
"pickExportDir": "Escolher Diretorio de Exportação",
|
"pickExportDir": "Escolher diretório para exportação",
|
||||||
"autoExportOnChanges": "Auto-exportar em mudanças",
|
"autoExportOnChanges": "Auto-exportar em mudanças",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Incluir configurações",
|
||||||
"filterVersionsByRegEx": "Filtrar Versões por Expressão Regular",
|
"filterVersionsByRegEx": "Filtrar versões por expressão regular",
|
||||||
"trySelectingSuggestedVersionCode": "Tente selecionar a versão sugerida",
|
"trySelectingSuggestedVersionCode": "Tente selecionar a versão sugerida",
|
||||||
"dontSortReleasesList": "Reter a ordem de lançamento da API",
|
"dontSortReleasesList": "Reter a ordem de lançamento da API",
|
||||||
"reverseSort": "Ordenação reversa",
|
"reverseSort": "Ordenação reversa",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Obter primeiro link",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Ignorar ordenação",
|
||||||
"debugMenu": "Menu Debug",
|
"debugMenu": "Menu debug",
|
||||||
"bgTaskStarted": "Tarefa em segundo-plano iniciada - verifique os logs.",
|
"bgTaskStarted": "Tarefa em segundo-plano iniciada - verifique os logs.",
|
||||||
"runBgCheckNow": "Execute a verificação de atualização em segundo-plano agora",
|
"runBgCheckNow": "Execute agora em segundo-plano a verificação de atualizações",
|
||||||
"versionExtractWholePage": "Aplicar Regex de Extração de Versão à Página Inteira",
|
"versionExtractWholePage": "Aplicar regex de extração de versão à página inteira",
|
||||||
"installing": "Instalando",
|
"installing": "Instalando",
|
||||||
"skipUpdateNotifications": "Pular notificações de update",
|
"skipUpdateNotifications": "Pular notificações de update",
|
||||||
"updatesAvailableNotifChannel": "Atualizações Disponíveis",
|
"updatesAvailableNotifChannel": "Atualizações disponíveis",
|
||||||
"appsUpdatedNotifChannel": "Aplicativos Atualizados",
|
"appsUpdatedNotifChannel": "Aplicativos atualizados",
|
||||||
"appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de aplicativos",
|
"appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de aplicativos",
|
||||||
"errorCheckingUpdatesNotifChannel": "Erro ao Procurar por Atualizações",
|
"errorCheckingUpdatesNotifChannel": "Erro ao procurar por atualizações",
|
||||||
"appsRemovedNotifChannel": "Aplicativos Removidos",
|
"appsRemovedNotifChannel": "Aplicativos removidos",
|
||||||
"downloadingXNotifChannel": "Baixando {}",
|
"downloadingXNotifChannel": "Baixando {}",
|
||||||
"completeAppInstallationNotifChannel": "Instalação completa do aplicativo",
|
"completeAppInstallationNotifChannel": "Instalação completa do aplicativo",
|
||||||
"checkingForUpdatesNotifChannel": "Checando por Atualizações",
|
"checkingForUpdatesNotifChannel": "Checando por atualizações",
|
||||||
"onlyCheckInstalledOrTrackOnlyApps": "Apenas checar apps instalados e 'Apenas Seguir' por updates",
|
"onlyCheckInstalledOrTrackOnlyApps": "Apenas verificar atualizações de aplicativos instalados e 'Apenas monitorar'",
|
||||||
"supportFixedAPKURL": "Suporte APK com URLs fixas",
|
"supportFixedAPKURL": "Suporte a APK com URLs fixas",
|
||||||
"selectX": "Selecionar {}",
|
"selectX": "Selecionar {}",
|
||||||
"parallelDownloads": "Permitir downloads paralelos",
|
"parallelDownloads": "Permitir downloads paralelos",
|
||||||
"installMethod": "Método de instalação",
|
"installMethod": "Método de instalação",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Root",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "Shizuku não está rodando",
|
"shizukuBinderNotFound": "O Shizuku não está rodando",
|
||||||
|
"useSystemFont": "Usar fonte padrão do sistema",
|
||||||
|
"systemFontError": "Erro ao carregar a fonte do sistema: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Usar versionCode do aplicativo como versão detectada pelo sistema operacional",
|
||||||
|
"requestHeader": "Requisitar cabeçalho",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Use o último upload de recursos como data de lançamento",
|
||||||
|
"defaultPseudoVersioningMethod": "Método de pseudo-versionamento padrão",
|
||||||
|
"partialAPKHash": "Hash APK parcial",
|
||||||
|
"APKLinkHash": "Hash de links APK",
|
||||||
|
"directAPKLink": "Link direto do APK",
|
||||||
|
"pseudoVersionInUse": "Uma pseudo-versão está em uso",
|
||||||
|
"installed": "Instalado",
|
||||||
|
"latest": "Mais recente",
|
||||||
|
"invertRegEx": "Inverter expressão regular",
|
||||||
|
"note": "Nota",
|
||||||
|
"selfHostedNote": "O menu suspenso \"{}\" pode ser usado para acessar instâncias auto-hospedadas/personalizadas de qualquer fonte.",
|
||||||
|
"badDownload": "Não foi possível analisar o APK (transferência incompatível ou parcial)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Remover aplicativo?",
|
"one": "Remover aplicativo?",
|
||||||
"other": "Remover aplicativos?"
|
"other": "Remover aplicativos?"
|
||||||
},
|
},
|
||||||
"tooManyRequestsTryAgainInMinutes": {
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
"one": "Muitas solicitações (taxa limitada) - tente novamente em {} minuto",
|
"one": "Muitas solicitações (taxa de solicitações limitada) - tente novamente em {} minuto",
|
||||||
"other": "Muitas solicitações (taxa limitada) - tente novamente em {} minutos"
|
"other": "Muitas solicitações (taxa limitada) - tente novamente em {} minutos"
|
||||||
},
|
},
|
||||||
"bgUpdateGotErrorRetryInMinutes": {
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
@ -325,19 +338,19 @@
|
|||||||
"other": "{} Dias"
|
"other": "{} Dias"
|
||||||
},
|
},
|
||||||
"clearedNLogsBeforeXAfterY": {
|
"clearedNLogsBeforeXAfterY": {
|
||||||
"one": "Limpo {n} log (antes = {antes}, depois = {depois})",
|
"one": "Foi limpo {n} log (antes = {antes}, depois = {depois})",
|
||||||
"other": "Limpados {n} logs (antes = {antes}, depois = {depois})"
|
"other": "Foram limpos {n} logs (antes = {antes}, depois = {depois})"
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesAvailable": {
|
"xAndNMoreUpdatesAvailable": {
|
||||||
"one": "{} e 1 outro app tem atualizações.",
|
"one": "{} e um outro aplicativo possui atualizações.",
|
||||||
"other": "{} e {} outros apps tem atualizações."
|
"other": "{} e {} outros aplicativo possuem atualizações."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesInstalled": {
|
"xAndNMoreUpdatesInstalled": {
|
||||||
"one": "{} e 1 outro app foi atualizado.",
|
"one": "{} e um outro aplicativo foram atualizado.",
|
||||||
"other": "{} e {} outros apps foram atualizados."
|
"other": "{} e {} outros aplicativos foram atualizados."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
"one": "{} e 1 outro app pode ter sido atualizado.",
|
"one": "{} e um outro aplicativo podem ter sido atualizados.",
|
||||||
"other": "{} e {} outros apps podem ter sido atualizados."
|
"other": "{} e {} outros aplicativos podem ter sido atualizados."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "Прогресс: {}%",
|
"percentProgress": "Прогресс: {}%",
|
||||||
"pleaseWait": "Пожалуйста, подождите",
|
"pleaseWait": "Пожалуйста, подождите",
|
||||||
"updateAvailable": "Доступно обновление",
|
"updateAvailable": "Доступно обновление",
|
||||||
"estimateInBracketsShort": "(Оценка)",
|
|
||||||
"notInstalled": "Не установлено",
|
"notInstalled": "Не установлено",
|
||||||
"estimateInBrackets": "(Оценка)",
|
"pseudoVersion": "псевдоверсия",
|
||||||
"selectAll": "Выбрать всё",
|
"selectAll": "Выбрать всё",
|
||||||
"deselectX": "Отменить выбор {}",
|
"deselectX": "Отменить выбор {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется на устройстве",
|
"xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется на устройстве",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Открепить",
|
"unpinFromTop": "Открепить",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Сбросить статус установки для выбранных приложений?",
|
"resetInstallStatusForSelectedAppsQuestion": "Сбросить статус установки для выбранных приложений?",
|
||||||
"installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, некорректная — из-за неудачных обновлений или других проблем",
|
"installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, некорректная — из-за неудачных обновлений или других проблем",
|
||||||
|
"customLinkMessage": "Эти ссылки работают на устройствах с установленным Obtainium",
|
||||||
|
"shareAppConfigLinks": "Поделиться конфигурацией приложения в виде HTML-ссылки",
|
||||||
"shareSelectedAppURLs": "Поделиться выбранными URL-адресами приложений",
|
"shareSelectedAppURLs": "Поделиться выбранными URL-адресами приложений",
|
||||||
"resetInstallStatus": "Сбросить статус установки",
|
"resetInstallStatus": "Сбросить статус установки",
|
||||||
"more": "Ещё",
|
"more": "Ещё",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Тёмная",
|
"dark": "Тёмная",
|
||||||
"light": "Светлая",
|
"light": "Светлая",
|
||||||
"followSystem": "Системная",
|
"followSystem": "Системная",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Использовать чёрную тему",
|
"useBlackTheme": "Использовать чёрную тему",
|
||||||
"appSortBy": "Сортировка приложений",
|
"appSortBy": "Сортировка приложений",
|
||||||
"authorName": "Автор/Название",
|
"authorName": "Автор/Название",
|
||||||
@ -133,7 +132,7 @@
|
|||||||
"close": "Закрыть",
|
"close": "Закрыть",
|
||||||
"share": "Поделиться",
|
"share": "Поделиться",
|
||||||
"appNotFound": "Приложение не найдено",
|
"appNotFound": "Приложение не найдено",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"obtainiumExportHyphenatedLowercase": "получение-экспорт",
|
||||||
"pickAnAPK": "Выберите APK-файл",
|
"pickAnAPK": "Выберите APK-файл",
|
||||||
"appHasMoreThanOnePackage": "{} имеет более одного пакета:",
|
"appHasMoreThanOnePackage": "{} имеет более одного пакета:",
|
||||||
"deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}",
|
"deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}",
|
||||||
@ -175,9 +174,8 @@
|
|||||||
"appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено",
|
"appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено",
|
||||||
"reposHaveMultipleApps": "В хранилище несколько приложений",
|
"reposHaveMultipleApps": "В хранилище несколько приложений",
|
||||||
"fdroidThirdPartyRepo": "Сторонние репозитории F-Droid",
|
"fdroidThirdPartyRepo": "Сторонние репозитории F-Droid",
|
||||||
"steam": "Steam",
|
"steamMobile": "Стим Мобайл",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "Стим-чат",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "Установить",
|
"install": "Установить",
|
||||||
"markInstalled": "Пометить как установленное",
|
"markInstalled": "Пометить как установленное",
|
||||||
"update": "Обновить",
|
"update": "Обновить",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Изменения",
|
"changes": "Изменения",
|
||||||
"releaseDate": "Дата выпуска",
|
"releaseDate": "Дата выпуска",
|
||||||
"importFromURLsInFile": "Импорт из файла URL-адресов (например: OPML)",
|
"importFromURLsInFile": "Импорт из файла URL-адресов (например: OPML)",
|
||||||
|
"versionDetectionExplanation": "Согласовать строку версии с версией, обнаруженной в ОС",
|
||||||
"versionDetection": "Определение версии",
|
"versionDetection": "Определение версии",
|
||||||
"standardVersionDetection": "Стандартное",
|
"standardVersionDetection": "Стандартное",
|
||||||
"groupByCategory": "Группировать по категориям",
|
"groupByCategory": "Группировать по категориям",
|
||||||
@ -235,7 +234,7 @@
|
|||||||
"addInfoInSettings": "Добавьте эту информацию в Настройки",
|
"addInfoInSettings": "Добавьте эту информацию в Настройки",
|
||||||
"githubSourceNote": "Используя ключ API можно обойти лимит запросов GitHub",
|
"githubSourceNote": "Используя ключ API можно обойти лимит запросов GitHub",
|
||||||
"gitlabSourceNote": "Без ключа API может не работать извлечение APK с GitLab",
|
"gitlabSourceNote": "Без ключа API может не работать извлечение APK с GitLab",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Сортировать только по последнему сегменту ссылки",
|
||||||
"filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску\n(регулярное выражение)",
|
"filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску\n(регулярное выражение)",
|
||||||
"customLinkFilterRegex": "Пользовательский фильтр ссылок APK\n(регулярное выражение, по умолчанию: '.apk$')",
|
"customLinkFilterRegex": "Пользовательский фильтр ссылок APK\n(регулярное выражение, по умолчанию: '.apk$')",
|
||||||
"appsPossiblyUpdated": "Попытки обновления приложений",
|
"appsPossiblyUpdated": "Попытки обновления приложений",
|
||||||
@ -245,10 +244,10 @@
|
|||||||
"backgroundUpdateReqsExplanation": "Фоновые обновления могут быть возможны не для всех приложений",
|
"backgroundUpdateReqsExplanation": "Фоновые обновления могут быть возможны не для всех приложений",
|
||||||
"backgroundUpdateLimitsExplanation": "Успешность фоновой установки можно определить только после открытия Obtainium",
|
"backgroundUpdateLimitsExplanation": "Успешность фоновой установки можно определить только после открытия Obtainium",
|
||||||
"verifyLatestTag": "Проверять тег 'latest'",
|
"verifyLatestTag": "Проверять тег 'latest'",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Фильтр для \"промежуточной\" ссылки для посещения",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Фильтрация ссылок по тексту ссылки",
|
||||||
"intermediateLinkNotFound": "Промежуточная ссылка не найдена",
|
"intermediateLinkNotFound": "Промежуточная ссылка не найдена",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Промежуточное звено",
|
||||||
"exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)",
|
"exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)",
|
||||||
"bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi",
|
"bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi",
|
||||||
"autoSelectHighestVersionCode": "Автоматически выбирать APK с актуальной версией кода",
|
"autoSelectHighestVersionCode": "Автоматически выбирать APK с актуальной версией кода",
|
||||||
@ -257,13 +256,13 @@
|
|||||||
"highlightTouchTargets": "Выделить менее очевидные элементы управления касанием",
|
"highlightTouchTargets": "Выделить менее очевидные элементы управления касанием",
|
||||||
"pickExportDir": "Выбрать каталог для экспорта",
|
"pickExportDir": "Выбрать каталог для экспорта",
|
||||||
"autoExportOnChanges": "Автоэкспорт при изменениях",
|
"autoExportOnChanges": "Автоэкспорт при изменениях",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Включить настройки",
|
||||||
"filterVersionsByRegEx": "Фильтровать версии по регулярному выражению",
|
"filterVersionsByRegEx": "Фильтровать версии по регулярному выражению",
|
||||||
"trySelectingSuggestedVersionCode": "Попробуйте выбрать предложенный код версии APK",
|
"trySelectingSuggestedVersionCode": "Попробуйте выбрать предложенный код версии APK",
|
||||||
"dontSortReleasesList": "Сохранить порядок релизов от API",
|
"dontSortReleasesList": "Сохранить порядок релизов от API",
|
||||||
"reverseSort": "Обратная сортировка",
|
"reverseSort": "Обратная сортировка",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Взять первую ссылку",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Пропустить сортировку",
|
||||||
"debugMenu": "Меню отладки",
|
"debugMenu": "Меню отладки",
|
||||||
"bgTaskStarted": "Фоновая задача начата — проверьте журналы",
|
"bgTaskStarted": "Фоновая задача начата — проверьте журналы",
|
||||||
"runBgCheckNow": "Запустить проверку фонового обновления сейчас",
|
"runBgCheckNow": "Запустить проверку фонового обновления сейчас",
|
||||||
@ -284,11 +283,24 @@
|
|||||||
"parallelDownloads": "Разрешить параллельные загрузки",
|
"parallelDownloads": "Разрешить параллельные загрузки",
|
||||||
"installMethod": "Метод установки",
|
"installMethod": "Метод установки",
|
||||||
"normal": "Нормальный",
|
"normal": "Нормальный",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Суперпользователь",
|
"root": "Суперпользователь",
|
||||||
"shizukuBinderNotFound": "Совместимый сервис Shizuku не найден",
|
"shizukuBinderNotFound": "Совместимый сервис Shizuku не найден",
|
||||||
"useSystemFont": "Использовать системный шрифт",
|
"useSystemFont": "Использовать системный шрифт",
|
||||||
"systemFontError": "Ошибка загрузки системного шрифта: {}",
|
"systemFontError": "Ошибка загрузки системного шрифта: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Использовать код версии приложения как версию, обнаруженную ОС",
|
||||||
|
"requestHeader": "Заголовок запроса",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Использовать последнюю загрузку ресурса в качестве даты выпуска",
|
||||||
|
"defaultPseudoVersioningMethod": "Метод псевдоверсионирования по умолчанию",
|
||||||
|
"partialAPKHash": "Частичный хэш APK",
|
||||||
|
"APKLinkHash": "Хеш ссылки APK",
|
||||||
|
"directAPKLink": "Прямая ссылка на APK",
|
||||||
|
"pseudoVersionInUse": "Используется псевдоверсия",
|
||||||
|
"installed": "Установлен",
|
||||||
|
"latest": "Последний",
|
||||||
|
"invertRegEx": "Инвертировать регулярное выражение",
|
||||||
|
"note": "Примечание",
|
||||||
|
"selfHostedNote": "Выпадающий список \"{}\" можно использовать для доступа к самостоятельно размещенным/настроенным экземплярам любого источника.",
|
||||||
|
"badDownload": "APK не удалось разобрать (несовместимая или неполная загрузка)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Удалить приложение?",
|
"one": "Удалить приложение?",
|
||||||
"other": "Удалить приложения?"
|
"other": "Удалить приложения?"
|
||||||
|
119
assets/translations/standardize.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// Take one (hardcoded) translation file and ensure that all other translation files have the same keys in the same order
|
||||||
|
// Then report which other translation files have identical items (or auto-translate them if a DeepL API key is provided)
|
||||||
|
|
||||||
|
const fs = require('fs')
|
||||||
|
const https = require('https')
|
||||||
|
|
||||||
|
const deeplAPIKey = process.argv[2]
|
||||||
|
|
||||||
|
const neverAutoTranslate = {
|
||||||
|
steamMobile: ['*'],
|
||||||
|
steamChat: ['*'],
|
||||||
|
root: ['*'],
|
||||||
|
obtainiumExportHyphenatedLowercase: ['*'],
|
||||||
|
theme: ['de'],
|
||||||
|
appId: ['de']
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateText = async (text, targetLang, authKey) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const postData = `text=${encodeURIComponent(text)}&target_lang=${encodeURIComponent(targetLang)}&source_lang=EN`
|
||||||
|
const options = {
|
||||||
|
hostname: 'api-free.deepl.com',
|
||||||
|
port: 443,
|
||||||
|
path: '/v2/translate',
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `DeepL-Auth-Key ${authKey}`,
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'Content-Length': Buffer.byteLength(postData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const req = https.request(options, (res) => {
|
||||||
|
let responseData = ''
|
||||||
|
res.on('data', (chunk) => {
|
||||||
|
responseData += chunk
|
||||||
|
})
|
||||||
|
res.on('end', () => {
|
||||||
|
try {
|
||||||
|
const jsonResponse = JSON.parse(responseData)
|
||||||
|
resolve(jsonResponse)
|
||||||
|
} catch (error) {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
req.on('error', (error) => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
req.write(postData)
|
||||||
|
req.end()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const translationsDir = __dirname
|
||||||
|
const templateFile = `${translationsDir}/en.json`
|
||||||
|
const otherFiles = fs.readdirSync(translationsDir).map(f => {
|
||||||
|
return `${translationsDir}/${f}`
|
||||||
|
}).filter(f => f.endsWith('.json') && f != templateFile)
|
||||||
|
|
||||||
|
const templateTranslation = require(templateFile)
|
||||||
|
|
||||||
|
|
||||||
|
otherFiles.forEach(file => {
|
||||||
|
const thisTranslationOriginal = require(file)
|
||||||
|
const thisTranslationNew = {}
|
||||||
|
Object.keys(templateTranslation).forEach(k => {
|
||||||
|
thisTranslationNew[k] = thisTranslationOriginal[k] || templateTranslation[k]
|
||||||
|
})
|
||||||
|
fs.writeFileSync(file, `${JSON.stringify(thisTranslationNew, null, ' ')}\n`)
|
||||||
|
})
|
||||||
|
|
||||||
|
for (let i in otherFiles) {
|
||||||
|
const file = otherFiles[i]
|
||||||
|
const thisTranslation = require(file)
|
||||||
|
const translationKeys = Object.keys(templateTranslation)
|
||||||
|
for (let j in translationKeys) {
|
||||||
|
const k = translationKeys[j]
|
||||||
|
if (JSON.stringify(thisTranslation[k]) == JSON.stringify(templateTranslation[k])) {
|
||||||
|
const lang = file.split('/').pop().split('.')[0]
|
||||||
|
if (!neverAutoTranslate[k] || (neverAutoTranslate[k].indexOf('*') < 0 && neverAutoTranslate[k].indexOf(lang) < 0)) {
|
||||||
|
const reportLine = `${file} :::: ${k} :::: ${JSON.stringify(thisTranslation[k])}`
|
||||||
|
if (deeplAPIKey) {
|
||||||
|
const translateFunc = async (str) => {
|
||||||
|
const response = await translateText(str, lang, deeplAPIKey)
|
||||||
|
if (response.translations) {
|
||||||
|
return response.translations[0].text
|
||||||
|
} else {
|
||||||
|
throw JSON.stringify(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (typeof templateTranslation[k] == 'string') {
|
||||||
|
thisTranslation[k] = await translateFunc(thisTranslation[k])
|
||||||
|
} else {
|
||||||
|
const subKeys = Object.keys(templateTranslation[k])
|
||||||
|
for (let n in subKeys) {
|
||||||
|
const kk = subKeys[n]
|
||||||
|
thisTranslation[k][kk] = await translateFunc(thisTranslation[k][kk])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof e == 'string') {
|
||||||
|
console.log(`${reportLine} :::: ${e}`)
|
||||||
|
} else {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(reportLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fs.writeFileSync(file, `${JSON.stringify(thisTranslation, null, ' ')}\n`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(e => console.error)
|
@ -5,26 +5,26 @@
|
|||||||
"urlMatchesNoSource": "URL matchar inte känd källa",
|
"urlMatchesNoSource": "URL matchar inte känd källa",
|
||||||
"cantInstallOlderVersion": "Kan inte installera en äldre version av en app",
|
"cantInstallOlderVersion": "Kan inte installera en äldre version av en app",
|
||||||
"appIdMismatch": "Nerladdat paket-ID matchar inte nuvarande App-ID",
|
"appIdMismatch": "Nerladdat paket-ID matchar inte nuvarande App-ID",
|
||||||
"functionNotImplemented": "This class has not implemented this function",
|
"functionNotImplemented": "Den här klassen har inte implementerat den här funktionen",
|
||||||
"placeholder": "Platshållare",
|
"placeholder": "Platshållare",
|
||||||
"someErrors": "Några fel uppstod",
|
"someErrors": "Några fel uppstod",
|
||||||
"unexpectedError": "Oväntat fel",
|
"unexpectedError": "Oväntat fel",
|
||||||
"ok": "Okej",
|
"ok": "Okej",
|
||||||
"and": "och",
|
"and": "och",
|
||||||
"githubPATLabel": "GitHub Personal Access Token (Increases Rate Limit)",
|
"githubPATLabel": "GitHub Personal Access Token (ökar hastighetsgräns)",
|
||||||
"includePrereleases": "Inkludera förreleaser",
|
"includePrereleases": "Inkludera förreleaser",
|
||||||
"fallbackToOlderReleases": "Fall tillbaka till äldre releaser",
|
"fallbackToOlderReleases": "Fall tillbaka till äldre releaser",
|
||||||
"filterReleaseTitlesByRegEx": "Filter Release Titles by Regular Expression",
|
"filterReleaseTitlesByRegEx": "Filtrera utgivningstitlar efter reguljärt uttryck",
|
||||||
"invalidRegEx": "Invalid regular expression",
|
"invalidRegEx": "Ogiltigt reguljärt uttryck",
|
||||||
"noDescription": "Ingen beskrivning",
|
"noDescription": "Ingen beskrivning",
|
||||||
"cancel": "Avbryt",
|
"cancel": "Avbryt",
|
||||||
"continue": "Fortsätt",
|
"continue": "Fortsätt",
|
||||||
"requiredInBrackets": "(Kräver)",
|
"requiredInBrackets": "(Kräver)",
|
||||||
"dropdownNoOptsError": "ERROR: DROPDOWN MUST HAVE AT LEAST ONE OPT",
|
"dropdownNoOptsError": "FEL: DROPDOWN MÅSTE HA MINST ETT OPT",
|
||||||
"colour": "Färg",
|
"colour": "Färg",
|
||||||
"githubStarredRepos": "GitHub Stjärnmärkta Förråd",
|
"githubStarredRepos": "GitHub Stjärnmärkta Förråd",
|
||||||
"uname": "Användarnamn",
|
"uname": "Användarnamn",
|
||||||
"wrongArgNum": "Wrong number of arguments provided",
|
"wrongArgNum": "Fel antal argument har angetts",
|
||||||
"xIsTrackOnly": "{} är 'Följ-Endast'",
|
"xIsTrackOnly": "{} är 'Följ-Endast'",
|
||||||
"source": "Källa",
|
"source": "Källa",
|
||||||
"app": "App",
|
"app": "App",
|
||||||
@ -48,12 +48,11 @@
|
|||||||
"noApps": "Inga Appar",
|
"noApps": "Inga Appar",
|
||||||
"noAppsForFilter": "Inga Appar för Filter",
|
"noAppsForFilter": "Inga Appar för Filter",
|
||||||
"byX": "Av {}",
|
"byX": "Av {}",
|
||||||
"percentProgress": "Progress: {}%",
|
"percentProgress": "Framsteg: {}%",
|
||||||
"pleaseWait": "Vänta",
|
"pleaseWait": "Vänta",
|
||||||
"updateAvailable": "Uppdatering Tillgänglig",
|
"updateAvailable": "Uppdatering Tillgänglig",
|
||||||
"estimateInBracketsShort": "(Est.)",
|
|
||||||
"notInstalled": "Inte Installerad",
|
"notInstalled": "Inte Installerad",
|
||||||
"estimateInBrackets": "(Uppskattning)",
|
"pseudoVersion": "pseudoversion",
|
||||||
"selectAll": "Välj Alla",
|
"selectAll": "Välj Alla",
|
||||||
"deselectX": "Avmarkera {}",
|
"deselectX": "Avmarkera {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} kommer tas bort från Obtainium men kommer vara fortsatt installerad på enheten.",
|
"xWillBeRemovedButRemainInstalled": "{} kommer tas bort från Obtainium men kommer vara fortsatt installerad på enheten.",
|
||||||
@ -73,12 +72,14 @@
|
|||||||
"unpinFromTop": "Avnåla",
|
"unpinFromTop": "Avnåla",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Återställ Installationsstatus för valda Appar?",
|
"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.",
|
"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.",
|
||||||
|
"customLinkMessage": "Dessa länkar fungerar på enheter med Obtainium installerat",
|
||||||
|
"shareAppConfigLinks": "Dela appkonfiguration som HTML-länk",
|
||||||
"shareSelectedAppURLs": "Dela Valda Appars URL:er",
|
"shareSelectedAppURLs": "Dela Valda Appars URL:er",
|
||||||
"resetInstallStatus": "Återställ Installationstatus",
|
"resetInstallStatus": "Återställ Installationstatus",
|
||||||
"more": "Mer",
|
"more": "Mer",
|
||||||
"removeOutdatedFilter": "Ta bort Utgånga App-filtret",
|
"removeOutdatedFilter": "Ta bort Utgånga App-filtret",
|
||||||
"showOutdatedOnly": "Visa Endast Utgånga Appar",
|
"showOutdatedOnly": "Visa Endast Utgånga Appar",
|
||||||
"filter": "Filter",
|
"filter": "Filtrera",
|
||||||
"filterActive": "Filter *",
|
"filterActive": "Filter *",
|
||||||
"filterApps": "Filtrera Appar",
|
"filterApps": "Filtrera Appar",
|
||||||
"appName": "Appnamn",
|
"appName": "Appnamn",
|
||||||
@ -94,7 +95,7 @@
|
|||||||
"obtainiumImport": "Obtainium Import",
|
"obtainiumImport": "Obtainium Import",
|
||||||
"importFromURLList": "Importera från URL-lista",
|
"importFromURLList": "Importera från URL-lista",
|
||||||
"searchQuery": "Sökförfrågan",
|
"searchQuery": "Sökförfrågan",
|
||||||
"appURLList": "App URL List",
|
"appURLList": "App URL-lista",
|
||||||
"line": "Linje",
|
"line": "Linje",
|
||||||
"searchX": "Sök {}",
|
"searchX": "Sök {}",
|
||||||
"noResults": "Inga resultat",
|
"noResults": "Inga resultat",
|
||||||
@ -110,18 +111,16 @@
|
|||||||
"dark": "Mörkt",
|
"dark": "Mörkt",
|
||||||
"light": "Ljust",
|
"light": "Ljust",
|
||||||
"followSystem": "Följ System",
|
"followSystem": "Följ System",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Använd svart tema",
|
"useBlackTheme": "Använd svart tema",
|
||||||
"appSortBy": "Sortera Appar via",
|
"appSortBy": "Sortera Appar via",
|
||||||
"authorName": "Utvecklare/Namn",
|
"authorName": "Utvecklare/Namn",
|
||||||
"nameAuthor": "Namn/Utvecklare",
|
"nameAuthor": "Namn/Utvecklare",
|
||||||
"asAdded": "As Added",
|
"asAdded": "Som tillagd",
|
||||||
"appSortOrder": "App Sort Order",
|
"appSortOrder": "Appsorteringsordning",
|
||||||
"ascending": "Stigande",
|
"ascending": "Stigande",
|
||||||
"descending": "Fallande",
|
"descending": "Fallande",
|
||||||
"bgUpdateCheckInterval": "Bakgrundsuppdateringskollfrekvens",
|
"bgUpdateCheckInterval": "Bakgrundsuppdateringskollfrekvens",
|
||||||
"neverManualOnly": "Never - Manual Only",
|
"neverManualOnly": "Aldrig - Endast manuell",
|
||||||
"appearance": "Utseende",
|
"appearance": "Utseende",
|
||||||
"showWebInAppView": "Visa källans hemsida i appvyn",
|
"showWebInAppView": "Visa källans hemsida i appvyn",
|
||||||
"pinUpdates": "Fäst uppdateringar högst upp i appvyn",
|
"pinUpdates": "Fäst uppdateringar högst upp i appvyn",
|
||||||
@ -145,7 +144,7 @@
|
|||||||
"noNewUpdates": "Inga nya uppdateringar.",
|
"noNewUpdates": "Inga nya uppdateringar.",
|
||||||
"xHasAnUpdate": "{} har en uppdatering.",
|
"xHasAnUpdate": "{} har en uppdatering.",
|
||||||
"appsUpdated": "Appar Uppdaterade",
|
"appsUpdated": "Appar Uppdaterade",
|
||||||
"appsUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were applied in the background",
|
"appsUpdatedNotifDescription": "Meddelar användaren att uppdateringar av en eller flera appar har tillämpats i bakgrunden",
|
||||||
"xWasUpdatedToY": "{} uppdaterades till {}.",
|
"xWasUpdatedToY": "{} uppdaterades till {}.",
|
||||||
"errorCheckingUpdates": "Fel vid uppdateringskoll",
|
"errorCheckingUpdates": "Fel vid uppdateringskoll",
|
||||||
"errorCheckingUpdatesNotifDescription": "En aviserings som visar när bakgrundsuppdateringarkollar misslyckas",
|
"errorCheckingUpdatesNotifDescription": "En aviserings som visar när bakgrundsuppdateringarkollar misslyckas",
|
||||||
@ -156,13 +155,13 @@
|
|||||||
"obtainiumMustBeOpenToInstallApps": "Obtainium måste vara öppet för att installera Appar",
|
"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",
|
"completeAppInstallationNotifDescription": "Frågar användaren att återvända till Obtaiunium när appinstallation är klar",
|
||||||
"checkingForUpdates": "Kollar efter Uppdateringar",
|
"checkingForUpdates": "Kollar efter Uppdateringar",
|
||||||
"checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates",
|
"checkingForUpdatesNotifDescription": "Övergående meddelande som visas när du söker efter uppdateringar",
|
||||||
"pleaseAllowInstallPerm": "Tillåt Obtanium att installera Appar",
|
"pleaseAllowInstallPerm": "Tillåt Obtanium att installera Appar",
|
||||||
"trackOnly": "Följ-Endast",
|
"trackOnly": "Följ-Endast",
|
||||||
"errorWithHttpStatusCode": "Fel {}",
|
"errorWithHttpStatusCode": "Fel {}",
|
||||||
"versionCorrectionDisabled": "Versionskorrigering inaktiverat (plugin verkar inte fungera)",
|
"versionCorrectionDisabled": "Versionskorrigering inaktiverat (plugin verkar inte fungera)",
|
||||||
"unknown": "Okänd",
|
"unknown": "Okänd",
|
||||||
"none": "None",
|
"none": "Ingen",
|
||||||
"never": "Aldrig",
|
"never": "Aldrig",
|
||||||
"latestVersionX": "Senaste Version: {}",
|
"latestVersionX": "Senaste Version: {}",
|
||||||
"installedVersionX": "Installerad Version: {}",
|
"installedVersionX": "Installerad Version: {}",
|
||||||
@ -175,7 +174,6 @@
|
|||||||
"appWithIdOrNameNotFound": "Ingen App funnen med det namnet eller ID",
|
"appWithIdOrNameNotFound": "Ingen App funnen med det namnet eller ID",
|
||||||
"reposHaveMultipleApps": "Förråd kan innehålla flera ApparR",
|
"reposHaveMultipleApps": "Förråd kan innehålla flera ApparR",
|
||||||
"fdroidThirdPartyRepo": "F-Droid Tredjeparts Förråd",
|
"fdroidThirdPartyRepo": "F-Droid Tredjeparts Förråd",
|
||||||
"steam": "Steam",
|
|
||||||
"steamMobile": "Steam Mobile",
|
"steamMobile": "Steam Mobile",
|
||||||
"steamChat": "Steam Chat",
|
"steamChat": "Steam Chat",
|
||||||
"install": "Installera",
|
"install": "Installera",
|
||||||
@ -184,9 +182,9 @@
|
|||||||
"markUpdated": "Märk Uppdaterad",
|
"markUpdated": "Märk Uppdaterad",
|
||||||
"additionalOptions": "Ytterligare Alternativ",
|
"additionalOptions": "Ytterligare Alternativ",
|
||||||
"disableVersionDetection": "Inaktivera versionsdetektering",
|
"disableVersionDetection": "Inaktivera versionsdetektering",
|
||||||
"noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.",
|
"noVersionDetectionExplanation": "Det här alternativet bör endast användas för appar där versionsidentifiering inte fungerar korrekt.",
|
||||||
"downloadingX": "Laddar ner {}",
|
"downloadingX": "Laddar ner {}",
|
||||||
"downloadNotifDescription": "Notifies the user of the progress in downloading an App",
|
"downloadNotifDescription": "Meddelar användaren om framstegen med att ladda ner en app",
|
||||||
"noAPKFound": "Ingen APK funnen",
|
"noAPKFound": "Ingen APK funnen",
|
||||||
"noVersionDetection": "Ingen versiondetektering",
|
"noVersionDetection": "Ingen versiondetektering",
|
||||||
"categorize": "Kategorisera",
|
"categorize": "Kategorisera",
|
||||||
@ -197,97 +195,127 @@
|
|||||||
"deleteCategoriesQuestion": "Ta Bort Kategorier?",
|
"deleteCategoriesQuestion": "Ta Bort Kategorier?",
|
||||||
"categoryDeleteWarning": "Alla Appar i de borttagna kategorierna kommer att märkas som okategoriserade.",
|
"categoryDeleteWarning": "Alla Appar i de borttagna kategorierna kommer att märkas som okategoriserade.",
|
||||||
"addCategory": "Lägg till Kategori",
|
"addCategory": "Lägg till Kategori",
|
||||||
"label": "Label",
|
"label": "Märka",
|
||||||
"language": "Språk",
|
"language": "Språk",
|
||||||
"copiedToClipboard": "Kopierat till Urklipp",
|
"copiedToClipboard": "Kopierat till Urklipp",
|
||||||
"storagePermissionDenied": "Lagringsbehörighet nekad",
|
"storagePermissionDenied": "Lagringsbehörighet nekad",
|
||||||
"selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.",
|
"selectedCategorizeWarning": "Detta kommer att ersätta alla befintliga kategoriinställningar för de valda apparna.",
|
||||||
"filterAPKsByRegEx": "Filter APKs by Regular Expression",
|
"filterAPKsByRegEx": "Filtrera APK-filer efter reguljärt uttryck",
|
||||||
"removeFromObtainium": "Ta bort från Obtainium",
|
"removeFromObtainium": "Ta bort från Obtainium",
|
||||||
"uninstallFromDevice": "Avinstallera från Enheten",
|
"uninstallFromDevice": "Avinstallera från Enheten",
|
||||||
"onlyWorksWithNonVersionDetectApps": "Fungerar bara för Appar med versionsdetektering inaktiverat..",
|
"onlyWorksWithNonVersionDetectApps": "Fungerar bara för Appar med versionsdetektering inaktiverat..",
|
||||||
"releaseDateAsVersion": "Använd releasedatum som version",
|
"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.",
|
"releaseDateAsVersionExplanation": "Det här alternativet bör endast användas för appar där versionsidentifiering inte fungerar korrekt, men ett releasedatum är tillgängligt.",
|
||||||
"changes": "Ändringar",
|
"changes": "Ändringar",
|
||||||
"releaseDate": "Releasedatum",
|
"releaseDate": "Releasedatum",
|
||||||
"importFromURLsInFile": "Importera från URL:er i fil (som OPML)",
|
"importFromURLsInFile": "Importera från URL:er i fil (som OPML)",
|
||||||
|
"versionDetectionExplanation": "Sammanställ versionssträng med version upptäckt från OS",
|
||||||
"versionDetection": "Versionsdetektering",
|
"versionDetection": "Versionsdetektering",
|
||||||
"standardVersionDetection": "Standardversionsdetektering",
|
"standardVersionDetection": "Standardversionsdetektering",
|
||||||
"groupByCategory": "Gruppera via Kategori",
|
"groupByCategory": "Gruppera via Kategori",
|
||||||
"autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible",
|
"autoApkFilterByArch": "Försök att filtrera APK-filer efter CPU-arkitektur om möjligt",
|
||||||
"overrideSource": "Överskrid Källa",
|
"overrideSource": "Överskrid Källa",
|
||||||
"dontShowAgain": "Visa inte detta igen",
|
"dontShowAgain": "Visa inte detta igen",
|
||||||
"dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar",
|
"dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar",
|
||||||
"dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar",
|
"dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar",
|
||||||
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
"moveNonInstalledAppsToBottom": "Flytta icke-installerade appar till botten av appvyn",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)",
|
"gitlabPATLabel": "GitLab Personal Access Token\\n(Möjliggör sökning och bättre APK-upptäckt)",
|
||||||
"about": "Om",
|
"about": "Om",
|
||||||
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
||||||
"checkOnStart": "Kolla efter uppdateringar vid start",
|
"checkOnStart": "Kolla efter uppdateringar vid start",
|
||||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
"tryInferAppIdFromCode": "Försök härleda app-id från källkoden",
|
||||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
"removeOnExternalUninstall": "Ta bort externt avinstallerade appar automatiskt",
|
||||||
"pickHighestVersionCode": "Auto-select highest version code APK",
|
"pickHighestVersionCode": "Välj automatiskt högsta versionskod APK",
|
||||||
"checkUpdateOnDetailPage": "Check for updates on opening an App detail page",
|
"checkUpdateOnDetailPage": "Sök efter uppdateringar om att öppna en app-detaljsida",
|
||||||
"disablePageTransitions": "Disable page transition animations",
|
"disablePageTransitions": "Inaktivera sidövergångsanimationer",
|
||||||
"reversePageTransitions": "Reverse page transition animations",
|
"reversePageTransitions": "Animeringar för omvänd sidövergång",
|
||||||
"minStarCount": "Minsta antal stjärnmarkeringar",
|
"minStarCount": "Minsta antal stjärnmarkeringar",
|
||||||
"addInfoBelow": "Lägg till denna information nedanför.",
|
"addInfoBelow": "Lägg till denna information nedanför.",
|
||||||
"addInfoInSettings": "Lägg till denna information i Inställningar.",
|
"addInfoInSettings": "Lägg till denna information i Inställningar.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHub-hastighetsbegränsning kan undvikas med en API-nyckel.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLab APK-extraktion kanske inte fungerar utan en API-nyckel.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Sortera endast efter det sista segmentet av länken",
|
||||||
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
"filterReleaseNotesByRegEx": "Filtrera versionskommentarer efter reguljärt uttryck",
|
||||||
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
"customLinkFilterRegex": "Anpassad APK-länkfiltrera efter reguljärt uttryck (standard '.apk$')",
|
||||||
"appsPossiblyUpdated": "App Updates Attempted",
|
"appsPossiblyUpdated": "Appuppdateringar försökte",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
|
"appsPossiblyUpdatedNotifDescription": "Meddelar användaren om att uppdateringar av en eller flera appar potentiellt har tillämpats i bakgrunden",
|
||||||
"xWasPossiblyUpdatedToY": "{} may have been updated to {}.",
|
"xWasPossiblyUpdatedToY": "{} kan ha uppdaterats till {}.",
|
||||||
"enableBackgroundUpdates": "Aktivera Bakgrundsuppdateringar",
|
"enableBackgroundUpdates": "Aktivera Bakgrundsuppdateringar",
|
||||||
"backgroundUpdateReqsExplanation": "Bakgrundsuppdateringar är inte möjligt för alla appar.",
|
"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.",
|
"backgroundUpdateLimitsExplanation": "Framgången för en bakgrundsinstallation kan bara avgöras när Obtainium öppnas.",
|
||||||
"verifyLatestTag": "Verifiera 'senaste'-taggen",
|
"verifyLatestTag": "Verifiera 'senaste'-taggen",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Filtrera för en \"mellanliggande\" länk att besöka",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Filtrera länkar efter länktext",
|
||||||
"intermediateLinkNotFound": "Intermediate link not found",
|
"intermediateLinkNotFound": "Mellanlänk hittades inte",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Mellanlänk",
|
||||||
"exemptFromBackgroundUpdates": "Undta från bakgrundsuppdateringar (om aktiverad)",
|
"exemptFromBackgroundUpdates": "Undta från bakgrundsuppdateringar (om aktiverad)",
|
||||||
"bgUpdatesOnWiFiOnly": "Inaktivera Bakgrundsuppdateringar utan WiFi",
|
"bgUpdatesOnWiFiOnly": "Inaktivera Bakgrundsuppdateringar utan WiFi",
|
||||||
"autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
|
"autoSelectHighestVersionCode": "Välj automatiskt högsta versionskod APK",
|
||||||
"versionExtractionRegEx": "Version Extraction RegEx",
|
"versionExtractionRegEx": "Version Extraction RegEx",
|
||||||
"matchGroupToUse": "Match Group to Use",
|
"matchGroupToUse": "Match Group to Use",
|
||||||
"highlightTouchTargets": "Highlight less obvious touch targets",
|
"highlightTouchTargets": "Markera mindre uppenbara beröringsobjekt",
|
||||||
"pickExportDir": "Välj Exportsökväg",
|
"pickExportDir": "Välj Exportsökväg",
|
||||||
"autoExportOnChanges": "Automatisk export vid ändringar",
|
"autoExportOnChanges": "Automatisk export vid ändringar",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Inkludera inställningar",
|
||||||
"filterVersionsByRegEx": "Filter Versions by Regular Expression",
|
"filterVersionsByRegEx": "Filtrera versioner efter reguljärt uttryck",
|
||||||
"trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK",
|
"trySelectingSuggestedVersionCode": "Försök att välja föreslagen versionCode APK",
|
||||||
"dontSortReleasesList": "Retain release order from API",
|
"dontSortReleasesList": "Behåll släpporder från API",
|
||||||
"reverseSort": "Omvänd sortering",
|
"reverseSort": "Omvänd sortering",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Ta första länken",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Hoppa över sortering",
|
||||||
"debugMenu": "Felsökningsmeny",
|
"debugMenu": "Felsökningsmeny",
|
||||||
"bgTaskStarted": "Background task started - check logs.",
|
"bgTaskStarted": "Bakgrundsuppgift startat - kontrollera loggar.",
|
||||||
"runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu",
|
"runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"versionExtractWholePage": "Tillämpa Regex för versionssträngextraktion på hela sidan",
|
||||||
"installMethod": "Installation method",
|
"installing": "Installerar",
|
||||||
"normal": "Normal",
|
"skipUpdateNotifications": "Hoppa över uppdateringsmeddelanden",
|
||||||
"shizuku": "Shizuku",
|
"updatesAvailableNotifChannel": "Uppdateringar tillgängliga",
|
||||||
"root": "Root",
|
"appsUpdatedNotifChannel": "Appar uppdaterade",
|
||||||
|
"appsPossiblyUpdatedNotifChannel": "Appuppdateringar försökte",
|
||||||
|
"errorCheckingUpdatesNotifChannel": "Fel vid sökning efter uppdateringar",
|
||||||
|
"appsRemovedNotifChannel": "Appar borttagna",
|
||||||
|
"downloadingXNotifChannel": "Laddar ner {}",
|
||||||
|
"completeAppInstallationNotifChannel": "Fullständig appinstallation",
|
||||||
|
"checkingForUpdatesNotifChannel": "Kollar efter uppdateringar",
|
||||||
|
"onlyCheckInstalledOrTrackOnlyApps": "Kontrollera bara installerade appar och endast spårbara appar för uppdateringar",
|
||||||
|
"supportFixedAPKURL": "Stöd fasta APK-webbadresser",
|
||||||
|
"selectX": "Välj {}",
|
||||||
|
"parallelDownloads": "Tillåt parallella nedladdningar",
|
||||||
|
"installMethod": "Installationsmetod",
|
||||||
|
"normal": "Vanligt",
|
||||||
|
"root": "Rot",
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"shizukuBinderNotFound": "Shizuku is not running",
|
||||||
|
"useSystemFont": "Använd systemteckensnittet",
|
||||||
|
"systemFontError": "Fel vid laddning av systemteckensnittet: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Använd appversionskoden som OS-upptäckt version",
|
||||||
|
"requestHeader": "Rubrik för begäran",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Använd senaste tillgångsuppladdning som releasedatum",
|
||||||
|
"defaultPseudoVersioningMethod": "Standard pseudoversionsmetod",
|
||||||
|
"partialAPKHash": "Delvis APK-hash",
|
||||||
|
"APKLinkHash": "APK-länk Hash",
|
||||||
|
"directAPKLink": "Direkt APK-länk",
|
||||||
|
"pseudoVersionInUse": "En pseudoversion används",
|
||||||
|
"installed": "Installerad",
|
||||||
|
"latest": "Senast",
|
||||||
|
"invertRegEx": "Invertera reguljärt uttryck",
|
||||||
|
"note": "Anmärkning",
|
||||||
|
"selfHostedNote": "Rullgardinsmenyn \"{}\" kan användas för att nå självhostade/anpassade instanser av valfri källa.",
|
||||||
|
"badDownload": "APK kunde inte analyseras (inkompatibel eller partiell nedladdning)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Ta Bort App?",
|
"one": "Ta Bort App?",
|
||||||
"other": "Ta Bort Appar?"
|
"other": "Ta Bort Appar?"
|
||||||
},
|
},
|
||||||
"tooManyRequestsTryAgainInMinutes": {
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
"one": "Too many requests (rate limited) - try again in {} minute",
|
"one": "För många förfrågningar (begränsat pris) - försök igen om {} minut",
|
||||||
"other": "Too many requests (rate limited) - try again in {} minutes"
|
"other": "För många förfrågningar (begränsat pris) - försök igen om {} minuter"
|
||||||
},
|
},
|
||||||
"bgUpdateGotErrorRetryInMinutes": {
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
"one": "BG update checking encountered a {}, will schedule a retry check in {} minute",
|
"one": "BG-uppdateringskontroll påträffade en {}, kommer att schemalägga ett nytt försök om {} minut",
|
||||||
"other": "BG update checking encountered a {}, will schedule a retry check in {} minutes"
|
"other": "BG-uppdateringskontroll påträffade en {}, kommer att schemalägga ett nytt försök om {} minuter"
|
||||||
},
|
},
|
||||||
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||||
"one": "BG update checking found {} update - will notify user if needed",
|
"one": "BG-uppdateringskontroll hittades {} uppdatering - kommer att meddela användaren om det behövs",
|
||||||
"other": "BG update checking found {} updates - will notify user if needed"
|
"other": "BG-uppdateringskontroll hittades {} uppdateringar - kommer att meddela användaren om det behövs"
|
||||||
},
|
},
|
||||||
"apps": {
|
"apps": {
|
||||||
"one": "{} App",
|
"one": "{} App",
|
||||||
|
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "İlerleme: {}%",
|
"percentProgress": "İlerleme: {}%",
|
||||||
"pleaseWait": "Lütfen Bekleyin",
|
"pleaseWait": "Lütfen Bekleyin",
|
||||||
"updateAvailable": "Güncelleme Var",
|
"updateAvailable": "Güncelleme Var",
|
||||||
"estimateInBracketsShort": "(Est.)",
|
|
||||||
"notInstalled": "Yüklenmedi",
|
"notInstalled": "Yüklenmedi",
|
||||||
"estimateInBrackets": "(Tahmini)",
|
"pseudoVersion": "sözde versiyon",
|
||||||
"selectAll": "Hepsini Seç",
|
"selectAll": "Hepsini Seç",
|
||||||
"deselectX": "{}'yi Seçimden Kaldır",
|
"deselectX": "{}'yi Seçimden Kaldır",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} Obtainium'dan kaldırılacak ancak cihazınızda yüklü kalacaktır.",
|
"xWillBeRemovedButRemainInstalled": "{} Obtainium'dan kaldırılacak ancak cihazınızda yüklü kalacaktır.",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Üstten Kaldır",
|
"unpinFromTop": "Üstten Kaldır",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "Seçilen Uygulamaların Yükleme Durumunu Sıfırlamak İstiyor musunuz?",
|
"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.",
|
"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.",
|
||||||
|
"customLinkMessage": "Bu bağlantılar Obtainium'un kurulu olduğu cihazlarda çalışır",
|
||||||
|
"shareAppConfigLinks": "Uygulama yapılandırmasını HTML bağlantısı olarak paylaş",
|
||||||
"shareSelectedAppURLs": "Seçilen Uygulama URL'larını Paylaş",
|
"shareSelectedAppURLs": "Seçilen Uygulama URL'larını Paylaş",
|
||||||
"resetInstallStatus": "Yükleme Durumunu Sıfırla",
|
"resetInstallStatus": "Yükleme Durumunu Sıfırla",
|
||||||
"more": "Daha Fazla",
|
"more": "Daha Fazla",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Koyu",
|
"dark": "Koyu",
|
||||||
"light": "Aydınlık",
|
"light": "Aydınlık",
|
||||||
"followSystem": "Sistemi Takip Et",
|
"followSystem": "Sistemi Takip Et",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Saf siyah koyu temasını kullan",
|
"useBlackTheme": "Saf siyah koyu temasını kullan",
|
||||||
"appSortBy": "Uygulama Sıralama Ölçütü",
|
"appSortBy": "Uygulama Sıralama Ölçütü",
|
||||||
"authorName": "Yazar/Ad",
|
"authorName": "Yazar/Ad",
|
||||||
@ -175,8 +174,7 @@
|
|||||||
"appWithIdOrNameNotFound": "Bu kimlik veya ada sahip bir uygulama bulunamadı",
|
"appWithIdOrNameNotFound": "Bu kimlik veya ada sahip bir uygulama bulunamadı",
|
||||||
"reposHaveMultipleApps": "Depolar birden fazla uygulama içerebilir",
|
"reposHaveMultipleApps": "Depolar birden fazla uygulama içerebilir",
|
||||||
"fdroidThirdPartyRepo": "F-Droid Üçüncü Taraf Depo",
|
"fdroidThirdPartyRepo": "F-Droid Üçüncü Taraf Depo",
|
||||||
"steam": "Steam",
|
"steamMobile": "Buhar Mobil",
|
||||||
"steamMobile": "Steam Mobile",
|
|
||||||
"steamChat": "Steam Sohbet",
|
"steamChat": "Steam Sohbet",
|
||||||
"install": "Yükle",
|
"install": "Yükle",
|
||||||
"markInstalled": "Yüklendi olarak İşaretle",
|
"markInstalled": "Yüklendi olarak İşaretle",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "Değişiklikler",
|
"changes": "Değişiklikler",
|
||||||
"releaseDate": "Yayın Tarihi",
|
"releaseDate": "Yayın Tarihi",
|
||||||
"importFromURLsInFile": "Dosyadaki URL'lerden İçe Aktar",
|
"importFromURLsInFile": "Dosyadaki URL'lerden İçe Aktar",
|
||||||
|
"versionDetectionExplanation": "Sürüm dizesini işletim sistemi tarafından algılanan sürümle uzlaştır",
|
||||||
"versionDetection": "Sürüm Tespiti",
|
"versionDetection": "Sürüm Tespiti",
|
||||||
"standardVersionDetection": "Standart sürüm tespiti",
|
"standardVersionDetection": "Standart sürüm tespiti",
|
||||||
"groupByCategory": "Kategoriye Göre Grupla",
|
"groupByCategory": "Kategoriye Göre Grupla",
|
||||||
@ -235,7 +234,7 @@
|
|||||||
"addInfoInSettings": "Bu bilgiyi Ayarlar'da ekleyin.",
|
"addInfoInSettings": "Bu bilgiyi Ayarlar'da ekleyin.",
|
||||||
"githubSourceNote": "GitHub hız sınırlaması bir API anahtarı kullanılarak atlanabilir.",
|
"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.",
|
"gitlabSourceNote": "GitLab APK çıkarma işlemi bir API anahtarı olmadan çalışmayabilir.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Bağlantının yalnızca son bölümüne göre sırala",
|
||||||
"filterReleaseNotesByRegEx": "Sürüm Notlarını Düzenli İfade ile Filtrele",
|
"filterReleaseNotesByRegEx": "Sürüm Notlarını Düzenli İfade ile Filtrele",
|
||||||
"customLinkFilterRegex": "Özel APK Bağlantı Filtresi Düzenli İfade ile (Varsayılan '.apk$')",
|
"customLinkFilterRegex": "Özel APK Bağlantı Filtresi Düzenli İfade ile (Varsayılan '.apk$')",
|
||||||
"appsPossiblyUpdated": "Uygulama Güncellemeleri Denendi",
|
"appsPossiblyUpdated": "Uygulama Güncellemeleri Denendi",
|
||||||
@ -245,10 +244,10 @@
|
|||||||
"backgroundUpdateReqsExplanation": "Arka plan güncellemeleri tüm uygulamalar için mümkün olmayabilir.",
|
"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.",
|
"backgroundUpdateLimitsExplanation": "Arka plan kurulumunun başarısı, Obtainium'un açıldığında ancak belirlenebilir.",
|
||||||
"verifyLatestTag": "'latest' etiketini doğrula",
|
"verifyLatestTag": "'latest' etiketini doğrula",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Ziyaret Edilecek 'Orta Düzey' Bağlantıyı Filtrele",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Bağlantıları bağlantı metnine göre filtrele",
|
||||||
"intermediateLinkNotFound": "Ara bağlantı bulunamadı",
|
"intermediateLinkNotFound": "Ara bağlantı bulunamadı",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Ara bağlantı",
|
||||||
"exemptFromBackgroundUpdates": "Arka plan güncellemelerinden muaf tut (etkinse)",
|
"exemptFromBackgroundUpdates": "Arka plan güncellemelerinden muaf tut (etkinse)",
|
||||||
"bgUpdatesOnWiFiOnly": "WiFi olmadığında arka plan güncellemelerini devre dışı bırak",
|
"bgUpdatesOnWiFiOnly": "WiFi olmadığında arka plan güncellemelerini devre dışı bırak",
|
||||||
"autoSelectHighestVersionCode": "Otomatik olarak en yüksek sürüm kodunu seç",
|
"autoSelectHighestVersionCode": "Otomatik olarak en yüksek sürüm kodunu seç",
|
||||||
@ -257,13 +256,13 @@
|
|||||||
"highlightTouchTargets": "Daha az belirgin dokunma hedeflerini vurgula",
|
"highlightTouchTargets": "Daha az belirgin dokunma hedeflerini vurgula",
|
||||||
"pickExportDir": "Dışa Aktarılacak Klasörü Seç",
|
"pickExportDir": "Dışa Aktarılacak Klasörü Seç",
|
||||||
"autoExportOnChanges": "Değişikliklerde otomatik olarak dışa aktar",
|
"autoExportOnChanges": "Değişikliklerde otomatik olarak dışa aktar",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Ayarları dahil et",
|
||||||
"filterVersionsByRegEx": "Sürümleri Düzenli İfade ile Filtrele",
|
"filterVersionsByRegEx": "Sürümleri Düzenli İfade ile Filtrele",
|
||||||
"trySelectingSuggestedVersionCode": "Önerilen sürüm kodunu seçmeyi dene",
|
"trySelectingSuggestedVersionCode": "Önerilen sürüm kodunu seçmeyi dene",
|
||||||
"dontSortReleasesList": "API'den sıralama düzenini koru",
|
"dontSortReleasesList": "API'den sıralama düzenini koru",
|
||||||
"reverseSort": "Ters sıralama",
|
"reverseSort": "Ters sıralama",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "İlk bağlantıyı al",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Sıralamayı atla",
|
||||||
"debugMenu": "Hata Ayıklama Menüsü",
|
"debugMenu": "Hata Ayıklama Menüsü",
|
||||||
"bgTaskStarted": "Arka plan görevi başladı - günlükleri kontrol et.",
|
"bgTaskStarted": "Arka plan görevi başladı - günlükleri kontrol et.",
|
||||||
"runBgCheckNow": "Arka Plan Güncelleme Kontrolünü Şimdi Çalıştır",
|
"runBgCheckNow": "Arka Plan Güncelleme Kontrolünü Şimdi Çalıştır",
|
||||||
@ -279,14 +278,29 @@
|
|||||||
"completeAppInstallationNotifChannel": "Uygulama Kurulumu Tamamlandı",
|
"completeAppInstallationNotifChannel": "Uygulama Kurulumu Tamamlandı",
|
||||||
"checkingForUpdatesNotifChannel": "Güncellemeler Kontrol Ediliyor",
|
"checkingForUpdatesNotifChannel": "Güncellemeler Kontrol Ediliyor",
|
||||||
"onlyCheckInstalledOrTrackOnlyApps": "Yalnızca yüklü ve Yalnızca İzleme Uygulamalarını güncelleme",
|
"onlyCheckInstalledOrTrackOnlyApps": "Yalnızca yüklü ve Yalnızca İzleme Uygulamalarını güncelleme",
|
||||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
"supportFixedAPKURL": "Sabit APK URL'lerini destekleyin",
|
||||||
"selectX": "Select {}",
|
"selectX": "Seçme {}",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "Paralel indirmelere izin ver",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "Kurulum yöntemi",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"shizuku": "Shizuku",
|
"root": "Kök",
|
||||||
"root": "Root",
|
|
||||||
"shizukuBinderNotFound": "Shizuku is not running",
|
"shizukuBinderNotFound": "Shizuku is not running",
|
||||||
|
"useSystemFont": "Sistem yazı tipini kullan",
|
||||||
|
"systemFontError": "Sistem yazı tipi yüklenirken hata oluştu: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Uygulama versionCode'unu işletim sistemi tarafından algılanan sürüm olarak kullan",
|
||||||
|
"requestHeader": "Başlık talep et",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Yayın tarihi olarak en son öğe yüklemesini kullan",
|
||||||
|
"defaultPseudoVersioningMethod": "Varsayılan Sözde Sürüm Oluşturma Yöntemi",
|
||||||
|
"partialAPKHash": "Kısmi APK Karması",
|
||||||
|
"APKLinkHash": "APK Bağlantı Karması",
|
||||||
|
"directAPKLink": "Doğrudan APK Bağlantısı",
|
||||||
|
"pseudoVersionInUse": "Sözde Versiyon Kullanımda",
|
||||||
|
"installed": "Kurulmuş",
|
||||||
|
"latest": "En sonuncu",
|
||||||
|
"invertRegEx": "Normal ifadeyi ters çevir",
|
||||||
|
"note": "Not",
|
||||||
|
"selfHostedNote": "\"{}\" açılır menüsü, herhangi bir kaynağın kendi kendine barındırılan/özel örneklerine ulaşmak için kullanılabilir.",
|
||||||
|
"badDownload": "APK ayrıştırılamadı (uyumsuz veya kısmi indirme)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Uygulamayı Kaldır?",
|
"one": "Uygulamayı Kaldır?",
|
||||||
"other": "Uygulamaları Kaldır?"
|
"other": "Uygulamaları Kaldır?"
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"unexpectedError": "Lỗi không mong đợi",
|
"unexpectedError": "Lỗi không mong đợi",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"and": "và",
|
"and": "và",
|
||||||
"githubPATLabel": "Mã thông báo truy cập cá nhân GitHub (Tăng tốc độ giới hạn)",
|
"githubPATLabel": "GitHub Token (Tăng tốc độ, giới hạn)",
|
||||||
"includePrereleases": "Bao gồm các bản phát hành trước",
|
"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",
|
"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",
|
"filterReleaseTitlesByRegEx": "Lọc tiêu đề bản phát hành theo biểu thức chính quy",
|
||||||
@ -25,16 +25,16 @@
|
|||||||
"githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub",
|
"githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub",
|
||||||
"uname": "Tên người dùng",
|
"uname": "Tên người dùng",
|
||||||
"wrongArgNum": "Số lượng đối số được cung cấp sai",
|
"wrongArgNum": "Số lượng đối số được cung cấp sai",
|
||||||
"xIsTrackOnly": "{}là Chỉ-Theo dõi",
|
"xIsTrackOnly": "{} là Chỉ theo dõi",
|
||||||
"source": "Nguồn",
|
"source": "Nguồn",
|
||||||
"app": "Ứng dụng",
|
"app": "Ứng dụng",
|
||||||
"appsFromSourceAreTrackOnly": "Các ứng dụng từ nguồn này là 'Chỉ-Theo dõi'.",
|
"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'.",
|
"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ó.",
|
"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",
|
"cancelled": "Đã hủy",
|
||||||
"appAlreadyAdded": "Ứng dụng được thêm rồi",
|
"appAlreadyAdded": "Ứng dụng được thêm rồi",
|
||||||
"alreadyUpToDateQuestion": "Ứng dụng đã được cập nhật?",
|
"alreadyUpToDateQuestion": "Ứng dụng đã được cập nhật?",
|
||||||
"addApp": "Thêm ứng dụng",
|
"addApp": "Thêm",
|
||||||
"appSourceURL": "URL nguồn ứng dụng",
|
"appSourceURL": "URL nguồn ứng dụng",
|
||||||
"error": "Lỗi",
|
"error": "Lỗi",
|
||||||
"add": "Thêm",
|
"add": "Thêm",
|
||||||
@ -42,18 +42,17 @@
|
|||||||
"search": "Tìm kiếm",
|
"search": "Tìm kiếm",
|
||||||
"additionalOptsFor": "Tùy chọn bổ sung cho {}",
|
"additionalOptsFor": "Tùy chọn bổ sung cho {}",
|
||||||
"supportedSources": "Nguồn được hỗ trợ",
|
"supportedSources": "Nguồn được hỗ trợ",
|
||||||
"trackOnlyInBrackets": "(Chỉ-Theo dõi)",
|
"trackOnlyInBrackets": "(Chỉ theo dõi)",
|
||||||
"searchableInBrackets": "(Có thể tìm kiếm)",
|
"searchableInBrackets": "(Có thể tìm kiếm)",
|
||||||
"appsString": "Ứng dụng",
|
"appsString": "Ứng dụng",
|
||||||
"noApps": "Không có ứng dụng",
|
"noApps": "Không có ứng dụng",
|
||||||
"noAppsForFilter": "Không có ứng dụng cho bộ lọc",
|
"noAppsForFilter": "Không có ứng dụng cho bộ lọc",
|
||||||
"byX": "Bởi {}",
|
"byX": "Bởi {}",
|
||||||
"percentProgress": "Tiến triển: {}%",
|
"percentProgress": "Đang tải {}%",
|
||||||
"pleaseWait": "Vui lòng chờ",
|
"pleaseWait": "Vui lòng chờ",
|
||||||
"updateAvailable": "Có sẵn bản cập nhật",
|
"updateAvailable": "Có sẵn bản cập nhật",
|
||||||
"estimateInBracketsShort": "(Ước lượng.)",
|
|
||||||
"notInstalled": "Chưa cài đặt",
|
"notInstalled": "Chưa cài đặt",
|
||||||
"estimateInBrackets": "(Ước lượng)",
|
"pseudoVersion": "phiên bản giả",
|
||||||
"selectAll": "Chọn tất cả",
|
"selectAll": "Chọn tất cả",
|
||||||
"deselectX": "Bỏ chọn {}",
|
"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ị.",
|
"xWillBeRemovedButRemainInstalled": "{} sẽ bị xóa khỏi Obtainium nhưng vẫn còn cài đặt trên thiết bị.",
|
||||||
@ -61,7 +60,7 @@
|
|||||||
"removeSelectedApps": "Xóa ứng dụng đã chọn",
|
"removeSelectedApps": "Xóa ứng dụng đã chọn",
|
||||||
"updateX": "Cập nhật {}",
|
"updateX": "Cập nhật {}",
|
||||||
"installX": "Cài đặt {}",
|
"installX": "Cài đặt {}",
|
||||||
"markXTrackOnlyAsUpdated": "Đánh dấu {}\n(Chỉ-Theo dõi)\nnhư là đã cập nhật",
|
"markXTrackOnlyAsUpdated": "Đánh dấu {}\n(Chỉ theo dõi)\nnhư là đã cập nhật",
|
||||||
"changeX": "Thay đổi {}",
|
"changeX": "Thay đổi {}",
|
||||||
"installUpdateApps": "Cài đặt/Cập nhật ứng dụng",
|
"installUpdateApps": "Cài đặt/Cập nhật ứng dụng",
|
||||||
"installUpdateSelectedApps": "Cài đặt/Cập nhật ứng dụng đã chọn",
|
"installUpdateSelectedApps": "Cài đặt/Cập nhật ứng dụng đã chọn",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "Bỏ ghim khỏi đầ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?",
|
"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.",
|
"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.",
|
||||||
|
"customLinkMessage": "Các liên kết này hoạt động trên các thiết bị có cài đặt Gainium",
|
||||||
|
"shareAppConfigLinks": "Chia sẻ cấu hình ứng dụng dưới dạng liên kết HTML",
|
||||||
"shareSelectedAppURLs": "Chia sẻ URL ứng dụng đã chọn",
|
"shareSelectedAppURLs": "Chia sẻ URL ứng dụng đã chọn",
|
||||||
"resetInstallStatus": "Đặt lại trạng thái cài đặt",
|
"resetInstallStatus": "Đặt lại trạng thái cài đặt",
|
||||||
"more": "Nhiều hơn",
|
"more": "Nhiều hơn",
|
||||||
@ -88,10 +89,10 @@
|
|||||||
"importExport": "Nhập/Xuất",
|
"importExport": "Nhập/Xuất",
|
||||||
"settings": "Cài đặt",
|
"settings": "Cài đặt",
|
||||||
"exportedTo": "Đã xuất sang {}",
|
"exportedTo": "Đã xuất sang {}",
|
||||||
"obtainiumExport": "Xuất Obtainium",
|
"obtainiumExport": "Xuất",
|
||||||
"invalidInput": "Đầu vào không hợp lệ",
|
"invalidInput": "Đầu vào không hợp lệ",
|
||||||
"importedX": "Đã nhập {}",
|
"importedX": "Đã nhập {}",
|
||||||
"obtainiumImport": "Nhập Obtainium",
|
"obtainiumImport": "Nhập",
|
||||||
"importFromURLList": "Nhập từ danh sách URL",
|
"importFromURLList": "Nhập từ danh sách URL",
|
||||||
"searchQuery": "Truy vấn tìm kiếm",
|
"searchQuery": "Truy vấn tìm kiếm",
|
||||||
"appURLList": "Danh sách URL ứng dụng",
|
"appURLList": "Danh sách URL ứng dụng",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "Tối",
|
"dark": "Tối",
|
||||||
"light": "Sáng",
|
"light": "Sáng",
|
||||||
"followSystem": "Theo hệ thống",
|
"followSystem": "Theo hệ thống",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "Nền đen",
|
"useBlackTheme": "Nền đen",
|
||||||
"appSortBy": "Sắp xếp ứng dụng",
|
"appSortBy": "Sắp xếp ứng dụng",
|
||||||
"authorName": "Tác giả",
|
"authorName": "Tác giả",
|
||||||
@ -120,13 +119,13 @@
|
|||||||
"appSortOrder": "Thứ tự sắp xếp",
|
"appSortOrder": "Thứ tự sắp xếp",
|
||||||
"ascending": "Tăng dần",
|
"ascending": "Tăng dần",
|
||||||
"descending": "Giảm dần",
|
"descending": "Giảm dần",
|
||||||
"bgUpdateCheckInterval": "Khoảng thời gian kiểm tra cập nhật nền",
|
"bgUpdateCheckInterval": "Thời gian tự động kiểm tra cập nhật",
|
||||||
"neverManualOnly": "Không bao giờ - Chỉ thủ công",
|
"neverManualOnly": "Không bao giờ",
|
||||||
"appearance": "Hiển thị",
|
"appearance": "Hiển thị",
|
||||||
"showWebInAppView": "Hiển thị trang web Nguồn trong chế độ xem Ứng dụng",
|
"showWebInAppView": "Hiển thị trang web Nguồn trong chế độ xem chi tiết Ứng dụng",
|
||||||
"pinUpdates": "Ghim nội dung cập nhật lên đầu chế độ xem Ứng dụng",
|
"pinUpdates": "Chuyển ứng dụng có phiên bản mới lên đầu danh sách",
|
||||||
"updates": "Cập nhật",
|
"updates": "Cập nhật",
|
||||||
"sourceSpecific": "Nguồn cụ thể",
|
"sourceSpecific": "Cài đặt Nguồn",
|
||||||
"appSource": "Nguồn ứng dụng",
|
"appSource": "Nguồn ứng dụng",
|
||||||
"noLogs": "Không có nhật ký",
|
"noLogs": "Không có nhật ký",
|
||||||
"appLogs": "Nhật ký ứng dụng",
|
"appLogs": "Nhật ký ứng dụng",
|
||||||
@ -158,7 +157,7 @@
|
|||||||
"checkingForUpdates": "Đang kiểm tra cập nhật",
|
"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",
|
"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",
|
"pleaseAllowInstallPerm": "Vui lòng cho phép Obtainium cài đặt Ứng dụng",
|
||||||
"trackOnly": "Chỉ-Theo dõi",
|
"trackOnly": "Chỉ theo dõi",
|
||||||
"errorWithHttpStatusCode": "Lỗ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)",
|
"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",
|
"unknown": "Không xác định",
|
||||||
@ -175,9 +174,8 @@
|
|||||||
"appWithIdOrNameNotFound": "Không tìm thấy ứng dụng nào có ID hoặc tên đó",
|
"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",
|
"reposHaveMultipleApps": "Kho có thể chứa nhiều Ứng dụng",
|
||||||
"fdroidThirdPartyRepo": "Kho lưu trữ bên thứ ba F-Droid",
|
"fdroidThirdPartyRepo": "Kho lưu trữ bên thứ ba F-Droid",
|
||||||
"steam": "Steam",
|
"steamMobile": "Điện thoại di động hơi nước",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "Trò chuyện hơi nước",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "Cài đặt",
|
"install": "Cài đặt",
|
||||||
"markInstalled": "Đánh dấu là đã cài đặt",
|
"markInstalled": "Đánh dấu là đã cài đặt",
|
||||||
"update": "Cập nhật",
|
"update": "Cập nhật",
|
||||||
@ -211,16 +209,17 @@
|
|||||||
"changes": "Thay đổi",
|
"changes": "Thay đổi",
|
||||||
"releaseDate": "Ngày phát hành",
|
"releaseDate": "Ngày phát hành",
|
||||||
"importFromURLsInFile": "Nhập từ URL trong Tệp (như OPML)",
|
"importFromURLsInFile": "Nhập từ URL trong Tệp (như OPML)",
|
||||||
|
"versionDetectionExplanation": "Đối chiếu chuỗi phiên bản với phiên bản được phát hiện từ hệ điều hành",
|
||||||
"versionDetection": "Phát hiện phiên bản",
|
"versionDetection": "Phát hiện phiên bản",
|
||||||
"standardVersionDetection": "Phát hiện phiên bản tiêu chuẩn",
|
"standardVersionDetection": "Phát hiện phiên bản tiêu chuẩn",
|
||||||
"groupByCategory": "Nhóm theo thể loại",
|
"groupByCategory": "Nhóm theo thể loại",
|
||||||
"autoApkFilterByArch": "Cố gắng lọc APK theo kiến trúc CPU nếu có thể",
|
"autoApkFilterByArch": "Cố gắng lọc APK theo kiến trúc CPU nếu có thể",
|
||||||
"overrideSource": "Ghi đè nguồn",
|
"overrideSource": "Ghi đè nguồn",
|
||||||
"dontShowAgain": "Đừng hiển thị thông tin này nữa",
|
"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'",
|
"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",
|
"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",
|
"moveNonInstalledAppsToBottom": "Chuyển Ứng dụng chưa được cài đặt xuống cuối danh sách",
|
||||||
"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)",
|
"gitlabPATLabel": "GitLab Token\n(Cho phép tìm kiếm và lọc APK tốt hơn)",
|
||||||
"about": "Giới thiệu",
|
"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)",
|
"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",
|
"checkOnStart": "Kiểm tra các bản cập nhật khi khởi động",
|
||||||
@ -235,20 +234,20 @@
|
|||||||
"addInfoInSettings": "Thêm thông tin này vào Cài đặt.",
|
"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.",
|
"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.",
|
"gitlabSourceNote": "Trích xuất APK GitLab có thể không hoạt động nếu không có khóa API.",
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Chỉ sắp xếp theo đoạn cuối của liên kết",
|
||||||
"filterReleaseNotesByRegEx": "Lọc ghi chú phát hành theo biểu thức chính quy",
|
"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$')",
|
"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",
|
"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",
|
"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 {}.",
|
"xWasPossiblyUpdatedToY": "{} có thể đã được cập nhật thành {}.",
|
||||||
"enableBackgroundUpdates": "Bật cập nhật nền",
|
"enableBackgroundUpdates": "Tự động cập nhật trong 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.",
|
"backgroundUpdateReqsExplanation": "Có thể không thực hiện được cập nhật trong 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.",
|
"backgroundUpdateLimitsExplanation": "Sự thành công của cài đặt trong nền chỉ có thể được xác định khi mở Obtainium.",
|
||||||
"verifyLatestTag": "Xác minh thẻ 'mới nhất'",
|
"verifyLatestTag": "Xác minh thẻ 'mới nhất'",
|
||||||
"intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
|
"intermediateLinkRegex": "Lọc tìm liên kết 'Trung cấp' để truy cập",
|
||||||
"filterByLinkText": "Filter links by link text",
|
"filterByLinkText": "Lọc liên kết theo văn bản liên kết",
|
||||||
"intermediateLinkNotFound": "Không tìm thấy liên kết trung gian",
|
"intermediateLinkNotFound": "Không tìm thấy liên kết trung gian",
|
||||||
"intermediateLink": "Intermediate link",
|
"intermediateLink": "Liên kết trung gian",
|
||||||
"exemptFromBackgroundUpdates": "Miễn cập nhật nền (nếu được bật)",
|
"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",
|
"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",
|
"autoSelectHighestVersionCode": "Tự động chọn APK mã phiên bản cao nhất",
|
||||||
@ -256,14 +255,14 @@
|
|||||||
"matchGroupToUse": "Nhóm đối sánh để sử dụng cho Regex trích xuất phiên bản",
|
"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",
|
"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",
|
"pickExportDir": "Chọn thư mục xuất",
|
||||||
"autoExportOnChanges": "Tự động xuất khi thay đổi",
|
"autoExportOnChanges": "Tự động xuất",
|
||||||
"includeSettings": "Include settings",
|
"includeSettings": "Bao gồm cài đặt ứng dụng",
|
||||||
"filterVersionsByRegEx": "Lọc phiên bản theo biểu thức chính quy",
|
"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",
|
"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",
|
"dontSortReleasesList": "Giữ lại thứ tự phát hành từ API",
|
||||||
"reverseSort": "Sắp xếp ngược",
|
"reverseSort": "Sắp xếp ngược",
|
||||||
"takeFirstLink": "Take first link",
|
"takeFirstLink": "Lấy liên kết đầu tiên",
|
||||||
"skipSort": "Skip sorting",
|
"skipSort": "Bỏ qua việc sắp xếp",
|
||||||
"debugMenu": "Danh sách gỡ lỗi",
|
"debugMenu": "Danh sách gỡ lỗi",
|
||||||
"bgTaskStarted": "Tác vụ nền đã bắt đầu - kiểm tra nhật ký.",
|
"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ờ",
|
"runBgCheckNow": "Chạy kiểm tra cập nhật nền ngay bây giờ",
|
||||||
@ -278,64 +277,79 @@
|
|||||||
"downloadingXNotifChannel": "Đang tải xuống {}",
|
"downloadingXNotifChannel": "Đang tải xuống {}",
|
||||||
"completeAppInstallationNotifChannel": "Hoàn tất cài đặt ứng dụng",
|
"completeAppInstallationNotifChannel": "Hoàn tất cài đặt ứng dụng",
|
||||||
"checkingForUpdatesNotifChannel": "Đang kiểm tra cập nhật",
|
"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",
|
"onlyCheckInstalledOrTrackOnlyApps": "Chỉ kiểm tra cập nhật các ứng dụng đã cài đặt và Chỉ theo dõi",
|
||||||
"supportFixedAPKURL": "Support fixed APK URLs",
|
"supportFixedAPKURL": "Hỗ trợ URL APK cố định",
|
||||||
"selectX": "Select {}",
|
"selectX": "Lựa chọn {}",
|
||||||
"parallelDownloads": "Allow parallel downloads",
|
"parallelDownloads": "Cho phép tải đa luồng",
|
||||||
"installMethod": "Installation method",
|
"installMethod": "Phương thức cài đặt",
|
||||||
"normal": "Normal",
|
"normal": "Mặc định",
|
||||||
"shizuku": "Shizuku",
|
|
||||||
"root": "Root",
|
"root": "Root",
|
||||||
"shizukuBinderNotFound": "Shizuku chưa khởi động",
|
"shizukuBinderNotFound": "Shizuku chưa khởi động",
|
||||||
"removeAppQuestion":{
|
"useSystemFont": "Sử dụng phông chữ hệ thống",
|
||||||
|
"systemFontError": "Lỗi tải phông chữ hệ thống: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Sử dụng Mã phiên bản ứng dụng làm phiên bản do hệ điều hành phát hiện",
|
||||||
|
"requestHeader": "Tiêu đề yêu cầu",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Sử dụng nội dung tải lên mới nhất làm ngày phát hành",
|
||||||
|
"defaultPseudoVersioningMethod": "Phương pháp tạo phiên bản giả mặc định",
|
||||||
|
"partialAPKHash": "Băm APK một phần",
|
||||||
|
"APKLinkHash": "Băm liên kết APK",
|
||||||
|
"directAPKLink": "Liên kết APK trực tiếp",
|
||||||
|
"pseudoVersionInUse": "Phiên bản giả đang được sử dụng",
|
||||||
|
"installed": "Đã cài đặt",
|
||||||
|
"latest": "Mới nhất",
|
||||||
|
"invertRegEx": "Đảo ngược biểu thức chính quy",
|
||||||
|
"note": "Note",
|
||||||
|
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
|
||||||
|
"badDownload": "The APK could not be parsed (incompatible or partial download)",
|
||||||
|
"removeAppQuestion": {
|
||||||
"one": "Gỡ ứng dụng?",
|
"one": "Gỡ ứng dụng?",
|
||||||
"other": "Gỡ ứng dụng?"
|
"other": "Gỡ ứng dụng?"
|
||||||
},
|
},
|
||||||
"tooManyRequestsTryAgainInMinutes":{
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
"one": "Quá nhiều yêu cầu (tốc độ giới hạn) - hãy thử lại sau {} phút",
|
"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"
|
"other": "Quá nhiều yêu cầu (tốc độ giới hạn) - hãy thử lại sau {} phút"
|
||||||
},
|
},
|
||||||
"bgUpdateGotErrorRetryInMinutes":{
|
"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",
|
"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"
|
"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":{
|
"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",
|
"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"
|
"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":{
|
"apps": {
|
||||||
"one": "{} Ứng dụng",
|
"one": "{} Ứng dụng",
|
||||||
"other": "{} Ứng dụng"
|
"other": "{} Ứng dụng"
|
||||||
},
|
},
|
||||||
"url":{
|
"url": {
|
||||||
"one": "{} URL",
|
"one": "{} URL",
|
||||||
"other": "{} URL"
|
"other": "{} URL"
|
||||||
},
|
},
|
||||||
"minute":{
|
"minute": {
|
||||||
"one": "{} Phút",
|
"one": "{} Phút",
|
||||||
"other": "{} Phút"
|
"other": "{} Phút"
|
||||||
},
|
},
|
||||||
"hour":{
|
"hour": {
|
||||||
"one": "{} Giờ",
|
"one": "{} Giờ",
|
||||||
"other": "{} Giờ"
|
"other": "{} Giờ"
|
||||||
},
|
},
|
||||||
"day":{
|
"day": {
|
||||||
"one": "{} Ngày",
|
"one": "{} Ngày",
|
||||||
"other": "{} ngày"
|
"other": "{} ngày"
|
||||||
},
|
},
|
||||||
"clearedNLogsBeforeXAfterY":{
|
"clearedNLogsBeforeXAfterY": {
|
||||||
"one": "Đã xóa {n} nhật ký (trước = {trước}, sau = {sau})",
|
"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})"
|
"other": "Đã xóa {n} nhật ký (trước = {trước}, sau = {sau})"
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesAvailable":{
|
"xAndNMoreUpdatesAvailable": {
|
||||||
"one": "{} và 1 ứng dụng khác có bản cập nhật.",
|
"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."
|
"other": "{} và {} ứng dụng khác có bản cập nhật."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesInstalled":{
|
"xAndNMoreUpdatesInstalled": {
|
||||||
"one": "{} và 1 ứng dụng khác đã được cập nhật.",
|
"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."
|
"other": "{} và {} ứng dụng khác đã được cập nhật."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesPossiblyInstalled":{
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
"one": "{} và 1 ứng dụng khác có thể đã được cập nhật.",
|
"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."
|
"other": "{} và {} ứng dụng khác có thể đã được cập nhật."
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,8 @@
|
|||||||
"percentProgress": "进度:{}%",
|
"percentProgress": "进度:{}%",
|
||||||
"pleaseWait": "请稍候",
|
"pleaseWait": "请稍候",
|
||||||
"updateAvailable": "更新可用",
|
"updateAvailable": "更新可用",
|
||||||
"estimateInBracketsShort": "(推测)",
|
|
||||||
"notInstalled": "未安装",
|
"notInstalled": "未安装",
|
||||||
"estimateInBrackets": "(推测)",
|
"pseudoVersion": "伪版本",
|
||||||
"selectAll": "全选",
|
"selectAll": "全选",
|
||||||
"deselectX": "取消选择 {}",
|
"deselectX": "取消选择 {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "“{}”将从 Obtainium 中删除,但仍安装在您的设备中。",
|
"xWillBeRemovedButRemainInstalled": "“{}”将从 Obtainium 中删除,但仍安装在您的设备中。",
|
||||||
@ -73,6 +72,8 @@
|
|||||||
"unpinFromTop": "取消置顶",
|
"unpinFromTop": "取消置顶",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "是否重置选中应用的安装状态?",
|
"resetInstallStatusForSelectedAppsQuestion": "是否重置选中应用的安装状态?",
|
||||||
"installStatusOfXWillBeResetExplanation": "选中应用的安装状态将会被重置。\n\n当更新安装失败或其他问题导致 Obtainium 中的应用版本显示错误时,可以尝试通过此方法解决。",
|
"installStatusOfXWillBeResetExplanation": "选中应用的安装状态将会被重置。\n\n当更新安装失败或其他问题导致 Obtainium 中的应用版本显示错误时,可以尝试通过此方法解决。",
|
||||||
|
"customLinkMessage": "这些链接适用于安装了 Gettingium 的设备",
|
||||||
|
"shareAppConfigLinks": "将应用程序配置共享为 HTML 链接",
|
||||||
"shareSelectedAppURLs": "分享选中应用的 URL",
|
"shareSelectedAppURLs": "分享选中应用的 URL",
|
||||||
"resetInstallStatus": "重置安装状态",
|
"resetInstallStatus": "重置安装状态",
|
||||||
"more": "更多",
|
"more": "更多",
|
||||||
@ -110,8 +111,6 @@
|
|||||||
"dark": "深色",
|
"dark": "深色",
|
||||||
"light": "浅色",
|
"light": "浅色",
|
||||||
"followSystem": "跟随系统",
|
"followSystem": "跟随系统",
|
||||||
"obtainium": "Obtainium",
|
|
||||||
"materialYou": "Material You",
|
|
||||||
"useBlackTheme": "使用纯黑深色主题",
|
"useBlackTheme": "使用纯黑深色主题",
|
||||||
"appSortBy": "排序依据",
|
"appSortBy": "排序依据",
|
||||||
"authorName": "作者 / 应用名称",
|
"authorName": "作者 / 应用名称",
|
||||||
@ -133,7 +132,7 @@
|
|||||||
"close": "关闭",
|
"close": "关闭",
|
||||||
"share": "分享",
|
"share": "分享",
|
||||||
"appNotFound": "未找到应用",
|
"appNotFound": "未找到应用",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"obtainiumExportHyphenatedLowercase": "获取出口",
|
||||||
"pickAnAPK": "选择一个 APK 文件",
|
"pickAnAPK": "选择一个 APK 文件",
|
||||||
"appHasMoreThanOnePackage": "“{}”有多个架构可用:",
|
"appHasMoreThanOnePackage": "“{}”有多个架构可用:",
|
||||||
"deviceSupportsXArch": "您的设备支持 {} 架构。",
|
"deviceSupportsXArch": "您的设备支持 {} 架构。",
|
||||||
@ -175,9 +174,8 @@
|
|||||||
"appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用",
|
"appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用",
|
||||||
"reposHaveMultipleApps": "存储库中可能包含多个应用",
|
"reposHaveMultipleApps": "存储库中可能包含多个应用",
|
||||||
"fdroidThirdPartyRepo": "F-Droid 第三方存储库",
|
"fdroidThirdPartyRepo": "F-Droid 第三方存储库",
|
||||||
"steam": "Steam",
|
"steamMobile": "蒸汽手机",
|
||||||
"steamMobile": "Steam Mobile",
|
"steamChat": "蒸汽聊天",
|
||||||
"steamChat": "Steam Chat",
|
|
||||||
"install": "安装",
|
"install": "安装",
|
||||||
"markInstalled": "标记为已安装",
|
"markInstalled": "标记为已安装",
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
@ -211,6 +209,7 @@
|
|||||||
"changes": "更新日志",
|
"changes": "更新日志",
|
||||||
"releaseDate": "发行日期",
|
"releaseDate": "发行日期",
|
||||||
"importFromURLsInFile": "从文件中的 URL 导入(如 OPML)",
|
"importFromURLsInFile": "从文件中的 URL 导入(如 OPML)",
|
||||||
|
"versionDetectionExplanation": "将版本字符串与操作系统检测到的版本进行协调",
|
||||||
"versionDetection": "版本检测",
|
"versionDetection": "版本检测",
|
||||||
"standardVersionDetection": "常规版本检测",
|
"standardVersionDetection": "常规版本检测",
|
||||||
"groupByCategory": "按类别分组显示",
|
"groupByCategory": "按类别分组显示",
|
||||||
@ -284,11 +283,24 @@
|
|||||||
"parallelDownloads": "启用并行下载",
|
"parallelDownloads": "启用并行下载",
|
||||||
"installMethod": "安装方式",
|
"installMethod": "安装方式",
|
||||||
"normal": "常规",
|
"normal": "常规",
|
||||||
"shizuku": "Shizuku",
|
"root": "root",
|
||||||
"root": "Root",
|
|
||||||
"shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
|
"shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
|
||||||
"useSystemFont": "使用系统字体",
|
"useSystemFont": "使用系统字体",
|
||||||
"systemFontError": "加载系统字体出错:{}",
|
"systemFontError": "加载系统字体出错:{}",
|
||||||
|
"useVersionCodeAsOSVersion": "使用应用程序版本代码作为操作系统检测到的版本",
|
||||||
|
"requestHeader": "请求标头",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "使用最新资产上传作为发布日期",
|
||||||
|
"defaultPseudoVersioningMethod": "默认伪版本控制方法",
|
||||||
|
"partialAPKHash": "部分 APK 哈希值",
|
||||||
|
"APKLinkHash": "APK 链接哈希",
|
||||||
|
"directAPKLink": "直接 APK 链接",
|
||||||
|
"pseudoVersionInUse": "伪版本正在使用",
|
||||||
|
"installed": "已安装",
|
||||||
|
"latest": "最新的",
|
||||||
|
"invertRegEx": "反转正则表达式",
|
||||||
|
"note": "备注",
|
||||||
|
"selfHostedNote": "{}\"下拉菜单可用于访问任何来源的自托管/自定义实例。",
|
||||||
|
"badDownload": "无法解析 APK(不兼容或部分下载)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "是否删除应用?",
|
"one": "是否删除应用?",
|
||||||
"other": "是否删除应用?"
|
"other": "是否删除应用?"
|
||||||
@ -341,4 +353,4 @@
|
|||||||
"one": "{} 和另外 1 个应用已尝试更新。",
|
"one": "{} 和另外 1 个应用已尝试更新。",
|
||||||
"other": "“{}”和另外 {} 个应用已尝试更新。"
|
"other": "“{}”和另外 {} 个应用已尝试更新。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
build.sh
@ -7,6 +7,10 @@ trap "cd "$CURR_DIR"" EXIT
|
|||||||
if [ -z "$1" ]; then
|
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
|
git fetch && git merge origin/main && git push # Typically run after a PR to main, so bring dev up to date
|
||||||
fi
|
fi
|
||||||
|
cd .flutter
|
||||||
|
git fetch
|
||||||
|
git checkout "$(flutter --version | head -2 | tail -1 | awk '{print $4}')" # Ensure included Flutter submodule version equals my environment
|
||||||
|
cd ..
|
||||||
rm ./build/app/outputs/flutter-apk/* 2>/dev/null # Get rid of older builds if any
|
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)
|
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
|
for file in ./build/app/outputs/flutter-apk/app-*normal*.apk*; do mv "$file" "${file//-normal/}"; done
|
||||||
|
54
fastlane/metadata/android/en-US/full_description.txt
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<p>Obtainium allows you to install and update Apps directly from their releases pages, and receive notifications when new releases are made available.</p>
|
||||||
|
<p>Read the <a href="https://github.com/ImranR98/Obtainium/wiki">Wiki</a></p>
|
||||||
|
<p>
|
||||||
|
<b>Currently supported App sources:</b>
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>Open Source - General:</p>
|
||||||
|
<ul>
|
||||||
|
<li>GitHub</li>
|
||||||
|
<li>GitLab</li>
|
||||||
|
<li>Codeberg</li>
|
||||||
|
<li>F-Droid</li>
|
||||||
|
<li>Third Party F-Droid Repos</li>
|
||||||
|
<li>IzzyOnDroid</li>
|
||||||
|
<li>SourceForge</li>
|
||||||
|
<li>SourceHut</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Other - General:</p>
|
||||||
|
<ul>
|
||||||
|
<li>APKPure</li>
|
||||||
|
<li>Aptoide</li>
|
||||||
|
<li>Uptodowng</li>
|
||||||
|
<li>APKMirror (Track-Only)</li>
|
||||||
|
<li>Huawei AppGallery</li>
|
||||||
|
<li>Jenkins Jobs</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Open Source - App-Specific:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Mullvad</li>
|
||||||
|
<li>Signal</li>
|
||||||
|
<li>VLC</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Other - App-Specific:</p>
|
||||||
|
<ul>
|
||||||
|
<li>WhatsApp</li>
|
||||||
|
<li>Telegram App</li>
|
||||||
|
<li>Neutron Code</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><p>"HTML" (Fallback): Any other URL that returns an HTML page with links to APK files</p></li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
<b>Limitations:</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For some sources, data is gathered using Web scraping and can easily break due to changes in website design. In such cases, more reliable methods may be unavailable.
|
||||||
|
</p>
|
BIN
fastlane/metadata/android/en-US/images/featureGraphic.png
Executable file
After Width: | Height: | Size: 66 KiB |
BIN
fastlane/metadata/android/en-US/images/icon.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
After Width: | Height: | Size: 234 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
After Width: | Height: | Size: 238 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
After Width: | Height: | Size: 140 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
After Width: | Height: | Size: 139 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
Normal file
After Width: | Height: | Size: 262 KiB |
1
fastlane/metadata/android/en-US/short_description.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Get android app updates directly from the source
|
1
fastlane/metadata/android/en-US/title.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Obtainium
|
@ -5,17 +5,20 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class APKCombo extends AppSource {
|
class APKCombo extends AppSource {
|
||||||
APKCombo() {
|
APKCombo() {
|
||||||
host = 'apkcombo.com';
|
hosts = ['apkcombo.com'];
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://(www\\.)?$host/+[^/]+/+[^/]+');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
var match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/+[^/]+/+[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
var match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -26,18 +29,19 @@ class APKCombo extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, String>?> getRequestHeaders(
|
Future<Map<String, String>?> getRequestHeaders(
|
||||||
{Map<String, dynamic> additionalSettings = const <String, dynamic>{},
|
Map<String, dynamic> additionalSettings,
|
||||||
bool forAPKDownload = false}) async {
|
{bool forAPKDownload = false}) async {
|
||||||
return {
|
return {
|
||||||
"User-Agent": "curl/8.0.1",
|
"User-Agent": "curl/8.0.1",
|
||||||
"Accept": "*/*",
|
"Accept": "*/*",
|
||||||
"Connection": "keep-alive",
|
"Connection": "keep-alive",
|
||||||
"Host": "$host"
|
"Host": hosts[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<MapEntry<String, String>>> getApkUrls(String standardUrl) async {
|
Future<List<MapEntry<String, String>>> getApkUrls(
|
||||||
var res = await sourceRequest('$standardUrl/download/apk');
|
String standardUrl, Map<String, dynamic> additionalSettings) async {
|
||||||
|
var res = await sourceRequest('$standardUrl/download/apk', {});
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
@ -70,9 +74,9 @@ class APKCombo extends AppSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> apkUrlPrefetchModifier(
|
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
|
||||||
String apkUrl, String standardUrl) async {
|
Map<String, dynamic> additionalSettings) async {
|
||||||
var freshURLs = await getApkUrls(standardUrl);
|
var freshURLs = await getApkUrls(standardUrl, additionalSettings);
|
||||||
var path2Match = Uri.parse(apkUrl).path;
|
var path2Match = Uri.parse(apkUrl).path;
|
||||||
for (var url in freshURLs) {
|
for (var url in freshURLs) {
|
||||||
if (Uri.parse(url.value).path == path2Match) {
|
if (Uri.parse(url.value).path == path2Match) {
|
||||||
@ -88,7 +92,7 @@ class APKCombo extends AppSource {
|
|||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
String appId = (await tryInferringAppId(standardUrl))!;
|
String appId = (await tryInferringAppId(standardUrl))!;
|
||||||
var preres = await sourceRequest(standardUrl);
|
var preres = await sourceRequest(standardUrl, additionalSettings);
|
||||||
if (preres.statusCode != 200) {
|
if (preres.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(preres);
|
throw getObtainiumHttpError(preres);
|
||||||
}
|
}
|
||||||
@ -112,7 +116,9 @@ class APKCombo extends AppSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return APKDetails(
|
return APKDetails(
|
||||||
version, await getApkUrls(standardUrl), AppNames(author, appName),
|
version,
|
||||||
|
await getApkUrls(standardUrl, additionalSettings),
|
||||||
|
AppNames(author, appName),
|
||||||
releaseDate: releaseDate);
|
releaseDate: releaseDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,9 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class APKMirror extends AppSource {
|
class APKMirror extends AppSource {
|
||||||
APKMirror() {
|
APKMirror() {
|
||||||
host = 'apkmirror.com';
|
hosts = ['apkmirror.com'];
|
||||||
enforceTrackOnly = true;
|
enforceTrackOnly = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
|
|
||||||
additionalSourceAppSpecificSettingFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
@ -32,13 +33,14 @@ class APKMirror extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx =
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExp('^https?://(www\\.)?$host/apk/[^/]+/[^/]+');
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/apk/[^/]+/[^/]+',
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -58,7 +60,7 @@ class APKMirror extends AppSource {
|
|||||||
true
|
true
|
||||||
? additionalSettings['filterReleaseTitlesByRegEx']
|
? additionalSettings['filterReleaseTitlesByRegEx']
|
||||||
: null;
|
: null;
|
||||||
Response res = await sourceRequest('$standardUrl/feed');
|
Response res = await sourceRequest('$standardUrl/feed', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var items = parse(res.body).querySelectorAll('item');
|
var items = parse(res.body).querySelectorAll('item');
|
||||||
dynamic targetRelease;
|
dynamic targetRelease;
|
||||||
@ -84,7 +86,7 @@ class APKMirror extends AppSource {
|
|||||||
dateString != null ? HttpDate.parse('$dateString GMT') : null;
|
dateString != null ? HttpDate.parse('$dateString GMT') : null;
|
||||||
String? version = titleString
|
String? version = titleString
|
||||||
?.substring(RegExp('[0-9]').firstMatch(titleString)?.start ?? 0,
|
?.substring(RegExp('[0-9]').firstMatch(titleString)?.start ?? 0,
|
||||||
RegExp(' by ').firstMatch(titleString)?.start ?? 0)
|
RegExp(' by ').allMatches(titleString).last.start)
|
||||||
.trim();
|
.trim();
|
||||||
if (version == null || version.isEmpty) {
|
if (version == null || version.isEmpty) {
|
||||||
version = titleString;
|
version = titleString;
|
||||||
|
@ -20,26 +20,29 @@ parseDateTimeMMMddCommayyyy(String? dateString) {
|
|||||||
|
|
||||||
class APKPure extends AppSource {
|
class APKPure extends AppSource {
|
||||||
APKPure() {
|
APKPure() {
|
||||||
host = 'apkpure.com';
|
hosts = ['apkpure.net', 'apkpure.com'];
|
||||||
allowSubDomains = true;
|
allowSubDomains = true;
|
||||||
naiveStandardVersionDetection = true;
|
naiveStandardVersionDetection = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegExB =
|
RegExp standardUrlRegExB = RegExp(
|
||||||
RegExp('^https?://m.$host/+[^/]+/+[^/]+(/+[^/]+)?');
|
'^https?://m.${getSourceRegex(hosts)}/+[^/]+/+[^/]+(/+[^/]+)?',
|
||||||
RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegExB.firstMatch(url);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
url = 'https://$host${Uri.parse(url).path}';
|
url = 'https://${getSourceRegex(hosts)}${Uri.parse(url).path}';
|
||||||
}
|
}
|
||||||
RegExp standardUrlRegExA =
|
RegExp standardUrlRegExA = RegExp(
|
||||||
RegExp('^https?://(www\\.)?$host/+[^/]+/+[^/]+(/+[^/]+)?');
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/+[^/]+/+[^/]+(/+[^/]+)?',
|
||||||
match = standardUrlRegExA.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
match = standardUrlRegExA.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -55,8 +58,8 @@ class APKPure extends AppSource {
|
|||||||
) async {
|
) async {
|
||||||
String appId = (await tryInferringAppId(standardUrl))!;
|
String appId = (await tryInferringAppId(standardUrl))!;
|
||||||
String host = Uri.parse(standardUrl).host;
|
String host = Uri.parse(standardUrl).host;
|
||||||
var res = await sourceRequest('$standardUrl/download');
|
var res = await sourceRequest('$standardUrl/download', additionalSettings);
|
||||||
var resChangelog = await sourceRequest(standardUrl);
|
var resChangelog = await sourceRequest(standardUrl, additionalSettings);
|
||||||
if (res.statusCode == 200 && resChangelog.statusCode == 200) {
|
if (res.statusCode == 200 && resChangelog.statusCode == 200) {
|
||||||
var html = parse(res.body);
|
var html = parse(res.body);
|
||||||
var htmlChangelog = parse(resChangelog.body);
|
var htmlChangelog = parse(resChangelog.body);
|
||||||
@ -69,7 +72,8 @@ class APKPure extends AppSource {
|
|||||||
DateTime? releaseDate = parseDateTimeMMMddCommayyyy(dateString);
|
DateTime? releaseDate = parseDateTimeMMMddCommayyyy(dateString);
|
||||||
String type = html.querySelector('a.info-tag')?.text.trim() ?? 'APK';
|
String type = html.querySelector('a.info-tag')?.text.trim() ?? 'APK';
|
||||||
List<MapEntry<String, String>> apkUrls = [
|
List<MapEntry<String, String>> apkUrls = [
|
||||||
MapEntry('$appId.apk', 'https://d.$host/b/$type/$appId?version=latest')
|
MapEntry('$appId.apk',
|
||||||
|
'https://d.${hosts.contains(host) ? 'cdnpure.com' : host}/b/$type/$appId?version=latest')
|
||||||
];
|
];
|
||||||
String author = html
|
String author = html
|
||||||
.querySelector('span.info-sdk')
|
.querySelector('span.info-sdk')
|
||||||
|
@ -6,30 +6,35 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class Aptoide extends AppSource {
|
class Aptoide extends AppSource {
|
||||||
Aptoide() {
|
Aptoide() {
|
||||||
host = 'aptoide.com';
|
hosts = ['aptoide.com'];
|
||||||
name = 'Aptoide';
|
name = 'Aptoide';
|
||||||
allowSubDomains = true;
|
allowSubDomains = true;
|
||||||
naiveStandardVersionDetection = true;
|
naiveStandardVersionDetection = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://([^\\.]+\\.){2,}$host');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://([^\\.]+\\.){2,}${getSourceRegex(hosts)}',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String?> tryInferringAppId(String standardUrl,
|
Future<String?> tryInferringAppId(String standardUrl,
|
||||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||||
return (await getAppDetailsJSON(standardUrl))['package'];
|
return (await getAppDetailsJSON(
|
||||||
|
standardUrl, additionalSettings))['package'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> getAppDetailsJSON(String standardUrl) async {
|
Future<Map<String, dynamic>> getAppDetailsJSON(
|
||||||
var res = await sourceRequest(standardUrl);
|
String standardUrl, Map<String, dynamic> additionalSettings) async {
|
||||||
|
var res = await sourceRequest(standardUrl, additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
@ -40,8 +45,8 @@ class Aptoide extends AppSource {
|
|||||||
} else {
|
} else {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
var res2 =
|
var res2 = await sourceRequest(
|
||||||
await sourceRequest('https://ws2.aptoide.com/api/7/getApp/app_id/$id');
|
'https://ws2.aptoide.com/api/7/getApp/app_id/$id', additionalSettings);
|
||||||
if (res2.statusCode != 200) {
|
if (res2.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
@ -53,7 +58,7 @@ class Aptoide extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
var appDetails = await getAppDetailsJSON(standardUrl);
|
var appDetails = await getAppDetailsJSON(standardUrl, additionalSettings);
|
||||||
String appName = appDetails['name'] ?? tr('app');
|
String appName = appDetails['name'] ?? tr('app');
|
||||||
String author = appDetails['developer']?['name'] ?? name;
|
String author = appDetails['developer']?['name'] ?? name;
|
||||||
String? dateStr = appDetails['updated'];
|
String? dateStr = appDetails['updated'];
|
||||||
|
@ -5,7 +5,7 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
class Codeberg extends AppSource {
|
class Codeberg extends AppSource {
|
||||||
GitHub gh = GitHub();
|
GitHub gh = GitHub();
|
||||||
Codeberg() {
|
Codeberg() {
|
||||||
host = 'codeberg.org';
|
hosts = ['codeberg.org'];
|
||||||
|
|
||||||
additionalSourceAppSpecificSettingFormItems =
|
additionalSourceAppSpecificSettingFormItems =
|
||||||
gh.additionalSourceAppSpecificSettingFormItems;
|
gh.additionalSourceAppSpecificSettingFormItems;
|
||||||
@ -16,12 +16,14 @@ class Codeberg extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://(www\\.)?$host/[^/]+/[^/]+');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/[^/]+/[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -35,7 +37,7 @@ class Codeberg extends AppSource {
|
|||||||
) async {
|
) async {
|
||||||
return await gh.getLatestAPKDetailsCommon2(standardUrl, additionalSettings,
|
return await gh.getLatestAPKDetailsCommon2(standardUrl, additionalSettings,
|
||||||
(bool useTagUrl) async {
|
(bool useTagUrl) async {
|
||||||
return 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100';
|
return 'https://${hosts[0]}/api/v1/repos${standardUrl.substring('https://${hosts[0]}'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100';
|
||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ class Codeberg extends AppSource {
|
|||||||
{Map<String, dynamic> querySettings = const {}}) async {
|
{Map<String, dynamic> querySettings = const {}}) async {
|
||||||
return gh.searchCommon(
|
return gh.searchCommon(
|
||||||
query,
|
query,
|
||||||
'https://$host/api/v1/repos/search?q=${Uri.encodeQueryComponent(query)}&limit=100',
|
'https://${hosts[0]}/api/v1/repos/search?q=${Uri.encodeQueryComponent(query)}&limit=100',
|
||||||
'data',
|
'data',
|
||||||
querySettings: querySettings);
|
querySettings: querySettings);
|
||||||
}
|
}
|
||||||
|
44
lib/app_sources/directAPKLink.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:obtainium/app_sources/html.dart';
|
||||||
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
|
class DirectAPKLink extends AppSource {
|
||||||
|
HTML html = HTML();
|
||||||
|
|
||||||
|
DirectAPKLink() {
|
||||||
|
neverAutoSelect = true;
|
||||||
|
name = tr('directAPKLink');
|
||||||
|
additionalSourceAppSpecificSettingFormItems = html
|
||||||
|
.additionalSourceAppSpecificSettingFormItems
|
||||||
|
.where((element) => element
|
||||||
|
.where((element) => element.key == 'requestHeader')
|
||||||
|
.isNotEmpty)
|
||||||
|
.toList();
|
||||||
|
excludeCommonSettingKeys = [
|
||||||
|
'versionExtractionRegEx',
|
||||||
|
'matchGroupToUse',
|
||||||
|
'versionDetection',
|
||||||
|
'useVersionCodeAsOSVersion',
|
||||||
|
'apkFilterRegEx',
|
||||||
|
'autoApkFilterByArch'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
|
String standardUrl,
|
||||||
|
Map<String, dynamic> additionalSettings,
|
||||||
|
) async {
|
||||||
|
var additionalSettingsNew =
|
||||||
|
getDefaultValuesFromFormItems(html.combinedAppSpecificSettingFormItems);
|
||||||
|
for (var s in additionalSettings.keys) {
|
||||||
|
if (additionalSettingsNew.containsKey(s)) {
|
||||||
|
additionalSettingsNew[s] = additionalSettings[s];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
additionalSettingsNew['defaultPseudoVersioningMethod'] = 'partialAPKHash';
|
||||||
|
additionalSettingsNew['directAPKLink'] = true;
|
||||||
|
additionalSettings['versionDetection'] = false;
|
||||||
|
return html.getLatestAPKDetails(standardUrl, additionalSettingsNew);
|
||||||
|
}
|
||||||
|
}
|
@ -3,13 +3,15 @@ import 'dart:convert';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:obtainium/app_sources/github.dart';
|
||||||
|
import 'package:obtainium/app_sources/gitlab.dart';
|
||||||
import 'package:obtainium/components/generated_form.dart';
|
import 'package:obtainium/components/generated_form.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
class FDroid extends AppSource {
|
class FDroid extends AppSource {
|
||||||
FDroid() {
|
FDroid() {
|
||||||
host = 'f-droid.org';
|
hosts = ['f-droid.org'];
|
||||||
name = tr('fdroid');
|
name = tr('fdroid');
|
||||||
naiveStandardVersionDetection = true;
|
naiveStandardVersionDetection = true;
|
||||||
canSearch = true;
|
canSearch = true;
|
||||||
@ -37,20 +39,22 @@ class FDroid extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegExB =
|
RegExp standardUrlRegExB = RegExp(
|
||||||
RegExp('^https?://(www\\.)?$host/+[^/]+/+packages/+[^/]+');
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/+[^/]+/+packages/+[^/]+',
|
||||||
RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegExB.firstMatch(url);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
url =
|
url =
|
||||||
'https://${Uri.parse(url.substring(0, match.end)).host}/packages/${Uri.parse(url).pathSegments.last}';
|
'https://${Uri.parse(match.group(0)!).host}/packages/${Uri.parse(url).pathSegments.last}';
|
||||||
}
|
}
|
||||||
RegExp standardUrlRegExA =
|
RegExp standardUrlRegExA = RegExp(
|
||||||
RegExp('^https?://(www\\.)?$host/+packages/+[^/]+');
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/+packages/+[^/]+',
|
||||||
match = standardUrlRegExA.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
match = standardUrlRegExA.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -67,35 +71,56 @@ class FDroid extends AppSource {
|
|||||||
String? appId = await tryInferringAppId(standardUrl);
|
String? appId = await tryInferringAppId(standardUrl);
|
||||||
String host = Uri.parse(standardUrl).host;
|
String host = Uri.parse(standardUrl).host;
|
||||||
var details = getAPKUrlsFromFDroidPackagesAPIResponse(
|
var details = getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||||
await sourceRequest('https://$host/api/v1/packages/$appId'),
|
await sourceRequest(
|
||||||
|
'https://$host/api/v1/packages/$appId', additionalSettings),
|
||||||
'https://$host/repo/$appId',
|
'https://$host/repo/$appId',
|
||||||
standardUrl,
|
standardUrl,
|
||||||
name,
|
name,
|
||||||
autoSelectHighestVersionCode:
|
additionalSettings: additionalSettings);
|
||||||
additionalSettings['autoSelectHighestVersionCode'] == true,
|
|
||||||
trySelectingSuggestedVersionCode:
|
|
||||||
additionalSettings['trySelectingSuggestedVersionCode'] == true,
|
|
||||||
filterVersionsByRegEx:
|
|
||||||
(additionalSettings['filterVersionsByRegEx'] as String?)
|
|
||||||
?.isNotEmpty ==
|
|
||||||
true
|
|
||||||
? additionalSettings['filterVersionsByRegEx']
|
|
||||||
: null);
|
|
||||||
if (!hostChanged) {
|
if (!hostChanged) {
|
||||||
try {
|
try {
|
||||||
var res = await sourceRequest(
|
var res = await sourceRequest(
|
||||||
'https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/$appId.yml');
|
'https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/$appId.yml',
|
||||||
String author = res.body
|
additionalSettings);
|
||||||
.split('\n')
|
var lines = res.body.split('\n');
|
||||||
.where((l) => l.startsWith('AuthorName: '))
|
var authorLines = lines.where((l) => l.startsWith('AuthorName: '));
|
||||||
.first
|
if (authorLines.isNotEmpty) {
|
||||||
.split(': ')
|
details.names.author =
|
||||||
.sublist(1)
|
authorLines.first.split(': ').sublist(1).join(': ');
|
||||||
.join(': ');
|
}
|
||||||
details.names.author = author;
|
var changelogUrls = lines
|
||||||
|
.where((l) => l.startsWith('Changelog: '))
|
||||||
|
.map((e) => e.split(' ').sublist(1).join(' '));
|
||||||
|
if (changelogUrls.isNotEmpty) {
|
||||||
|
details.changeLog = changelogUrls.first;
|
||||||
|
bool isGitHub = false;
|
||||||
|
bool isGitLab = false;
|
||||||
|
try {
|
||||||
|
GitHub().sourceSpecificStandardizeURL(details.changeLog!);
|
||||||
|
isGitHub = true;
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
GitLab().sourceSpecificStandardizeURL(details.changeLog!);
|
||||||
|
isGitLab = true;
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
if ((isGitHub || isGitLab) &&
|
||||||
|
(details.changeLog?.indexOf('/blob/') ?? -1) >= 0) {
|
||||||
|
details.changeLog = (await sourceRequest(
|
||||||
|
details.changeLog!.replaceFirst('/blob/', '/raw/'),
|
||||||
|
additionalSettings))
|
||||||
|
.body;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Fail silently
|
// Fail silently
|
||||||
}
|
}
|
||||||
|
if ((details.changeLog?.length ?? 0) > 2048) {
|
||||||
|
details.changeLog = '${details.changeLog!.substring(0, 2048)}...';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
@ -104,7 +129,7 @@ class FDroid extends AppSource {
|
|||||||
Future<Map<String, List<String>>> search(String query,
|
Future<Map<String, List<String>>> search(String query,
|
||||||
{Map<String, dynamic> querySettings = const {}}) async {
|
{Map<String, dynamic> querySettings = const {}}) async {
|
||||||
Response res = await sourceRequest(
|
Response res = await sourceRequest(
|
||||||
'https://search.$host/?q=${Uri.encodeQueryComponent(query)}');
|
'https://search.${hosts[0]}/?q=${Uri.encodeQueryComponent(query)}', {});
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
Map<String, List<String>> urlsWithDescriptions = {};
|
Map<String, List<String>> urlsWithDescriptions = {};
|
||||||
parse(res.body).querySelectorAll('.package-header').forEach((e) {
|
parse(res.body).querySelectorAll('.package-header').forEach((e) {
|
||||||
@ -132,12 +157,30 @@ class FDroid extends AppSource {
|
|||||||
|
|
||||||
APKDetails getAPKUrlsFromFDroidPackagesAPIResponse(
|
APKDetails getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||||
Response res, String apkUrlPrefix, String standardUrl, String sourceName,
|
Response res, String apkUrlPrefix, String standardUrl, String sourceName,
|
||||||
{bool autoSelectHighestVersionCode = false,
|
{Map<String, dynamic> additionalSettings = const {}}) {
|
||||||
bool trySelectingSuggestedVersionCode = false,
|
var autoSelectHighestVersionCode =
|
||||||
String? filterVersionsByRegEx}) {
|
additionalSettings['autoSelectHighestVersionCode'] == true;
|
||||||
|
var trySelectingSuggestedVersionCode =
|
||||||
|
additionalSettings['trySelectingSuggestedVersionCode'] == true;
|
||||||
|
var filterVersionsByRegEx =
|
||||||
|
(additionalSettings['filterVersionsByRegEx'] as String?)?.isNotEmpty ==
|
||||||
|
true
|
||||||
|
? additionalSettings['filterVersionsByRegEx']
|
||||||
|
: null;
|
||||||
|
var apkFilterRegEx =
|
||||||
|
(additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true
|
||||||
|
? additionalSettings['apkFilterRegEx']
|
||||||
|
: null;
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var response = jsonDecode(res.body);
|
var response = jsonDecode(res.body);
|
||||||
List<dynamic> releases = response['packages'] ?? [];
|
List<dynamic> releases = response['packages'] ?? [];
|
||||||
|
if (apkFilterRegEx != null) {
|
||||||
|
releases = releases.where((rel) {
|
||||||
|
String apk = '${apkUrlPrefix}_${rel['versionCode']}.apk';
|
||||||
|
return filterApks([MapEntry(apk, apk)], apkFilterRegEx, false)
|
||||||
|
.isNotEmpty;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
if (releases.isEmpty) {
|
if (releases.isEmpty) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
import 'package:obtainium/components/generated_form.dart';
|
import 'package:obtainium/components/generated_form.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
@ -10,6 +11,7 @@ class FDroidRepo extends AppSource {
|
|||||||
canSearch = true;
|
canSearch = true;
|
||||||
excludeFromMassSearch = true;
|
excludeFromMassSearch = true;
|
||||||
neverAutoSelect = true;
|
neverAutoSelect = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
|
|
||||||
additionalSourceAppSpecificSettingFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
@ -44,7 +46,7 @@ class FDroidRepo extends AppSource {
|
|||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
var standardUri = Uri.parse(url);
|
var standardUri = Uri.parse(url);
|
||||||
var pathSegments = standardUri.pathSegments;
|
var pathSegments = standardUri.pathSegments;
|
||||||
if (pathSegments.last == 'index.xml') {
|
if (pathSegments.isNotEmpty && pathSegments.last == 'index.xml') {
|
||||||
pathSegments.removeLast();
|
pathSegments.removeLast();
|
||||||
standardUri = standardUri.replace(path: pathSegments.join('/'));
|
standardUri = standardUri.replace(path: pathSegments.join('/'));
|
||||||
}
|
}
|
||||||
@ -59,7 +61,7 @@ class FDroidRepo extends AppSource {
|
|||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
url = removeQueryParamsFromUrl(standardizeUrl(url));
|
url = removeQueryParamsFromUrl(standardizeUrl(url));
|
||||||
var res = await sourceRequest('$url/index.xml');
|
var res = await sourceRequestWithURLVariants(url, {});
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var body = parse(res.body);
|
var body = parse(res.body);
|
||||||
Map<String, List<String>> results = {};
|
Map<String, List<String>> results = {};
|
||||||
@ -71,7 +73,11 @@ class FDroidRepo extends AppSource {
|
|||||||
appId.contains(query) ||
|
appId.contains(query) ||
|
||||||
appName.contains(query) ||
|
appName.contains(query) ||
|
||||||
appDesc.contains(query)) {
|
appDesc.contains(query)) {
|
||||||
results['$url?appId=$appId'] = [appName, appDesc];
|
results[
|
||||||
|
'${res.request!.url.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}?appId=$appId'] = [
|
||||||
|
appName,
|
||||||
|
appDesc
|
||||||
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
@ -101,6 +107,26 @@ class FDroidRepo extends AppSource {
|
|||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Response> sourceRequestWithURLVariants(
|
||||||
|
String url,
|
||||||
|
Map<String, dynamic> additionalSettings,
|
||||||
|
) async {
|
||||||
|
var res = await sourceRequest(
|
||||||
|
'$url${url.endsWith('/index.xml') ? '' : '/index.xml'}',
|
||||||
|
additionalSettings);
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
var base = url.endsWith('/index.xml')
|
||||||
|
? url.split('/').reversed.toList().sublist(1).reversed.join('/')
|
||||||
|
: url;
|
||||||
|
res = await sourceRequest('$base/repo/index.xml', additionalSettings);
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
res = await sourceRequest(
|
||||||
|
'$base/fdroid/repo/index.xml', additionalSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl,
|
String standardUrl,
|
||||||
@ -116,8 +142,8 @@ class FDroidRepo extends AppSource {
|
|||||||
if (appIdOrName == null) {
|
if (appIdOrName == null) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
var res = await sourceRequest(
|
var res =
|
||||||
'$standardUrl${standardUrl.endsWith('/index.xml') ? '' : '/index.xml'}');
|
await sourceRequestWithURLVariants(standardUrl, additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var body = parse(res.body);
|
var body = parse(res.body);
|
||||||
var foundApps = body.querySelectorAll('application').where((element) {
|
var foundApps = body.querySelectorAll('application').where((element) {
|
||||||
@ -166,7 +192,8 @@ class FDroidRepo extends AppSource {
|
|||||||
latestVersionReleases = [latestVersionReleases[0]];
|
latestVersionReleases = [latestVersionReleases[0]];
|
||||||
}
|
}
|
||||||
List<String> apkUrls = latestVersionReleases
|
List<String> apkUrls = latestVersionReleases
|
||||||
.map((e) => '$standardUrl/${e.querySelector('apkname')!.innerHtml}')
|
.map((e) =>
|
||||||
|
'${res.request!.url.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}/${e.querySelector('apkname')!.innerHtml}')
|
||||||
.toList();
|
.toList();
|
||||||
return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls),
|
return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls),
|
||||||
AppNames(authorName, appName),
|
AppNames(authorName, appName),
|
||||||
|
@ -14,8 +14,9 @@ import 'package:url_launcher/url_launcher_string.dart';
|
|||||||
|
|
||||||
class GitHub extends AppSource {
|
class GitHub extends AppSource {
|
||||||
GitHub() {
|
GitHub() {
|
||||||
host = 'github.com';
|
hosts = ['github.com'];
|
||||||
appIdInferIsOptional = true;
|
appIdInferIsOptional = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
|
|
||||||
sourceConfigSettingFormItems = [
|
sourceConfigSettingFormItems = [
|
||||||
GeneratedFormTextField('github-creds',
|
GeneratedFormTextField('github-creds',
|
||||||
@ -76,6 +77,10 @@ class GitHub extends AppSource {
|
|||||||
[
|
[
|
||||||
GeneratedFormSwitch('dontSortReleasesList',
|
GeneratedFormSwitch('dontSortReleasesList',
|
||||||
label: tr('dontSortReleasesList'))
|
label: tr('dontSortReleasesList'))
|
||||||
|
],
|
||||||
|
[
|
||||||
|
GeneratedFormSwitch('useLatestAssetDateAsReleaseDate',
|
||||||
|
label: tr('useLatestAssetDateAsReleaseDate'), defaultValue: false)
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -108,7 +113,8 @@ class GitHub extends AppSource {
|
|||||||
for (var path in possibleBuildGradleLocations) {
|
for (var path in possibleBuildGradleLocations) {
|
||||||
try {
|
try {
|
||||||
var res = await sourceRequest(
|
var res = await sourceRequest(
|
||||||
'${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path');
|
'${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path',
|
||||||
|
additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
try {
|
try {
|
||||||
var body = jsonDecode(res.body);
|
var body = jsonDecode(res.body);
|
||||||
@ -149,18 +155,20 @@ class GitHub extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://(www\\.)?$host/[^/]+/[^/]+');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/[^/]+/[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, String>?> getRequestHeaders(
|
Future<Map<String, String>?> getRequestHeaders(
|
||||||
{Map<String, dynamic> additionalSettings = const <String, dynamic>{},
|
Map<String, dynamic> additionalSettings,
|
||||||
bool forAPKDownload = false}) async {
|
{bool forAPKDownload = false}) async {
|
||||||
var token = await getTokenIfAny(additionalSettings);
|
var token = await getTokenIfAny(additionalSettings);
|
||||||
var headers = <String, String>{};
|
var headers = <String, String>{};
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
@ -203,11 +211,11 @@ class GitHub extends AppSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getAPIHost(Map<String, dynamic> additionalSettings) async =>
|
Future<String> getAPIHost(Map<String, dynamic> additionalSettings) async =>
|
||||||
'https://api.$host';
|
'https://api.${hosts[0]}';
|
||||||
|
|
||||||
Future<String> convertStandardUrlToAPIUrl(
|
Future<String> convertStandardUrlToAPIUrl(
|
||||||
String standardUrl, Map<String, dynamic> additionalSettings) async =>
|
String standardUrl, Map<String, dynamic> additionalSettings) async =>
|
||||||
'${await getAPIHost(additionalSettings)}/repos${standardUrl.substring('https://$host'.length)}';
|
'${await getAPIHost(additionalSettings)}/repos${standardUrl.substring('https://${hosts[0]}'.length)}';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? changeLogPageFromStandardUrl(String standardUrl) =>
|
String? changeLogPageFromStandardUrl(String standardUrl) =>
|
||||||
@ -234,11 +242,14 @@ class GitHub extends AppSource {
|
|||||||
bool verifyLatestTag = additionalSettings['verifyLatestTag'] == true;
|
bool verifyLatestTag = additionalSettings['verifyLatestTag'] == true;
|
||||||
bool dontSortReleasesList =
|
bool dontSortReleasesList =
|
||||||
additionalSettings['dontSortReleasesList'] == true;
|
additionalSettings['dontSortReleasesList'] == true;
|
||||||
|
bool useLatestAssetDateAsReleaseDate =
|
||||||
|
additionalSettings['useLatestAssetDateAsReleaseDate'] == true;
|
||||||
dynamic latestRelease;
|
dynamic latestRelease;
|
||||||
if (verifyLatestTag) {
|
if (verifyLatestTag) {
|
||||||
var temp = requestUrl.split('?');
|
var temp = requestUrl.split('?');
|
||||||
Response res = await sourceRequest(
|
Response res = await sourceRequest(
|
||||||
'${temp[0]}/latest${temp.length > 1 ? '?${temp.sublist(1).join('?')}' : ''}');
|
'${temp[0]}/latest${temp.length > 1 ? '?${temp.sublist(1).join('?')}' : ''}',
|
||||||
|
additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
if (onHttpErrorCode != null) {
|
if (onHttpErrorCode != null) {
|
||||||
onHttpErrorCode(res);
|
onHttpErrorCode(res);
|
||||||
@ -247,7 +258,7 @@ class GitHub extends AppSource {
|
|||||||
}
|
}
|
||||||
latestRelease = jsonDecode(res.body);
|
latestRelease = jsonDecode(res.body);
|
||||||
}
|
}
|
||||||
Response res = await sourceRequest(requestUrl);
|
Response res = await sourceRequest(requestUrl, additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var releases = jsonDecode(res.body) as List<dynamic>;
|
var releases = jsonDecode(res.body) as List<dynamic>;
|
||||||
if (latestRelease != null) {
|
if (latestRelease != null) {
|
||||||
@ -273,10 +284,31 @@ class GitHub extends AppSource {
|
|||||||
.toList() ??
|
.toList() ??
|
||||||
[];
|
[];
|
||||||
|
|
||||||
DateTime? getReleaseDateFromRelease(dynamic rel) =>
|
DateTime? getPublishDateFromRelease(dynamic rel) =>
|
||||||
rel?['published_at'] != null
|
rel?['published_at'] != null
|
||||||
? DateTime.parse(rel['published_at'])
|
? DateTime.parse(rel['published_at'])
|
||||||
: null;
|
: null;
|
||||||
|
DateTime? getNewestAssetDateFromRelease(dynamic rel) {
|
||||||
|
var t = (rel['assets'] as List<dynamic>?)
|
||||||
|
?.map((e) {
|
||||||
|
return e?['updated_at'] != null
|
||||||
|
? DateTime.parse(e['updated_at'])
|
||||||
|
: null;
|
||||||
|
})
|
||||||
|
.where((e) => e != null)
|
||||||
|
.toList();
|
||||||
|
t?.sort((a, b) => b!.compareTo(a!));
|
||||||
|
if (t?.isNotEmpty == true) {
|
||||||
|
return t!.first;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? getReleaseDateFromRelease(dynamic rel, bool useAssetDate) =>
|
||||||
|
!useAssetDate
|
||||||
|
? getPublishDateFromRelease(rel)
|
||||||
|
: getNewestAssetDateFromRelease(rel);
|
||||||
|
|
||||||
if (dontSortReleasesList) {
|
if (dontSortReleasesList) {
|
||||||
releases = releases.reversed.toList();
|
releases = releases.reversed.toList();
|
||||||
} else {
|
} else {
|
||||||
@ -301,8 +333,12 @@ class GitHub extends AppSource {
|
|||||||
(nameA as String).substring(matchA!.start, matchA.end),
|
(nameA as String).substring(matchA!.start, matchA.end),
|
||||||
(nameB as String).substring(matchB!.start, matchB.end));
|
(nameB as String).substring(matchB!.start, matchB.end));
|
||||||
} else {
|
} else {
|
||||||
return (getReleaseDateFromRelease(a) ?? DateTime(1))
|
return (getReleaseDateFromRelease(
|
||||||
.compareTo(getReleaseDateFromRelease(b) ?? DateTime(0));
|
a, useLatestAssetDateAsReleaseDate) ??
|
||||||
|
DateTime(1))
|
||||||
|
.compareTo(getReleaseDateFromRelease(
|
||||||
|
b, useLatestAssetDateAsReleaseDate) ??
|
||||||
|
DateTime(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -346,11 +382,8 @@ class GitHub extends AppSource {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var apkUrls = getReleaseAPKUrls(releases[i]);
|
var apkUrls = getReleaseAPKUrls(releases[i]);
|
||||||
if (additionalSettings['apkFilterRegEx'] != null) {
|
apkUrls = filterApks(apkUrls, additionalSettings['apkFilterRegEx'],
|
||||||
var reg = RegExp(additionalSettings['apkFilterRegEx']);
|
additionalSettings['invertAPKFilter']);
|
||||||
apkUrls =
|
|
||||||
apkUrls.where((element) => reg.hasMatch(element.key)).toList();
|
|
||||||
}
|
|
||||||
if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
|
if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -362,7 +395,8 @@ class GitHub extends AppSource {
|
|||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
String? version = targetRelease['tag_name'] ?? targetRelease['name'];
|
String? version = targetRelease['tag_name'] ?? targetRelease['name'];
|
||||||
DateTime? releaseDate = getReleaseDateFromRelease(targetRelease);
|
DateTime? releaseDate = getReleaseDateFromRelease(
|
||||||
|
targetRelease, useLatestAssetDateAsReleaseDate);
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
throw NoVersionError();
|
throw NoVersionError();
|
||||||
}
|
}
|
||||||
@ -424,7 +458,7 @@ class GitHub extends AppSource {
|
|||||||
String query, String requestUrl, String rootProp,
|
String query, String requestUrl, String rootProp,
|
||||||
{Function(Response)? onHttpErrorCode,
|
{Function(Response)? onHttpErrorCode,
|
||||||
Map<String, dynamic> querySettings = const {}}) async {
|
Map<String, dynamic> querySettings = const {}}) async {
|
||||||
Response res = await sourceRequest(requestUrl);
|
Response res = await sourceRequest(requestUrl, {});
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
int minStarCount = querySettings['minStarCount'] != null
|
int minStarCount = querySettings['minStarCount'] != null
|
||||||
? int.parse(querySettings['minStarCount'])
|
? int.parse(querySettings['minStarCount'])
|
||||||
|
@ -13,8 +13,9 @@ import 'package:url_launcher/url_launcher_string.dart';
|
|||||||
|
|
||||||
class GitLab extends AppSource {
|
class GitLab extends AppSource {
|
||||||
GitLab() {
|
GitLab() {
|
||||||
host = 'gitlab.com';
|
hosts = ['gitlab.com'];
|
||||||
canSearch = true;
|
canSearch = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
|
|
||||||
sourceConfigSettingFormItems = [
|
sourceConfigSettingFormItems = [
|
||||||
GeneratedFormTextField('gitlab-creds',
|
GeneratedFormTextField('gitlab-creds',
|
||||||
@ -52,12 +53,14 @@ class GitLab extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://(www\\.)?$host/[^/]+/[^/]+');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/[^/]+/[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getPATIfAny(Map<String, dynamic> additionalSettings) async {
|
Future<String?> getPATIfAny(Map<String, dynamic> additionalSettings) async {
|
||||||
@ -81,15 +84,15 @@ class GitLab extends AppSource {
|
|||||||
Future<Map<String, List<String>>> search(String query,
|
Future<Map<String, List<String>>> search(String query,
|
||||||
{Map<String, dynamic> querySettings = const {}}) async {
|
{Map<String, dynamic> querySettings = const {}}) async {
|
||||||
var url =
|
var url =
|
||||||
'https://$host/api/v4/projects?search=${Uri.encodeQueryComponent(query)}';
|
'https://${hosts[0]}/api/v4/projects?search=${Uri.encodeQueryComponent(query)}';
|
||||||
var res = await sourceRequest(url);
|
var res = await sourceRequest(url, {});
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
var json = jsonDecode(res.body) as List<dynamic>;
|
var json = jsonDecode(res.body) as List<dynamic>;
|
||||||
Map<String, List<String>> results = {};
|
Map<String, List<String>> results = {};
|
||||||
for (var element in json) {
|
for (var element in json) {
|
||||||
results['https://$host/${element['path_with_namespace']}'] = [
|
results['https://${hosts[0]}/${element['path_with_namespace']}'] = [
|
||||||
element['name_with_namespace'],
|
element['name_with_namespace'],
|
||||||
element['description'] ?? tr('noDescription')
|
element['description'] ?? tr('noDescription')
|
||||||
];
|
];
|
||||||
@ -113,7 +116,8 @@ class GitLab extends AppSource {
|
|||||||
if (PAT != null) {
|
if (PAT != null) {
|
||||||
var names = GitHub().getAppNames(standardUrl);
|
var names = GitHub().getAppNames(standardUrl);
|
||||||
Response res = await sourceRequest(
|
Response res = await sourceRequest(
|
||||||
'https://$host/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT');
|
'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT',
|
||||||
|
additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
@ -148,7 +152,8 @@ class GitLab extends AppSource {
|
|||||||
releaseDate: releaseDate);
|
releaseDate: releaseDate);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Response res = await sourceRequest('$standardUrl/-/tags?format=atom');
|
Response res = await sourceRequest(
|
||||||
|
'$standardUrl/-/tags?format=atom', additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ String ensureAbsoluteUrl(String ambiguousUrl, Uri referenceAbsoluteUrl) {
|
|||||||
.toList();
|
.toList();
|
||||||
String absoluteUrl;
|
String absoluteUrl;
|
||||||
if (ambiguousUrl.startsWith('/') || currPathSegments.isEmpty) {
|
if (ambiguousUrl.startsWith('/') || currPathSegments.isEmpty) {
|
||||||
|
absoluteUrl = '${referenceAbsoluteUrl.origin}$ambiguousUrl';
|
||||||
|
} else if (currPathSegments.isEmpty) {
|
||||||
absoluteUrl = '${referenceAbsoluteUrl.origin}/$ambiguousUrl';
|
absoluteUrl = '${referenceAbsoluteUrl.origin}/$ambiguousUrl';
|
||||||
} else if (ambiguousUrl.split('/').where((e) => e.isNotEmpty).length == 1) {
|
} else if (ambiguousUrl.split('/').where((e) => e.isNotEmpty).length == 1) {
|
||||||
absoluteUrl =
|
absoluteUrl =
|
||||||
@ -106,11 +108,7 @@ class HTML extends AppSource {
|
|||||||
[
|
[
|
||||||
GeneratedFormSwitch('versionExtractWholePage',
|
GeneratedFormSwitch('versionExtractWholePage',
|
||||||
label: tr('versionExtractWholePage'))
|
label: tr('versionExtractWholePage'))
|
||||||
],
|
]
|
||||||
[
|
|
||||||
GeneratedFormSwitch('supportFixedAPKURL',
|
|
||||||
defaultValue: true, label: tr('supportFixedAPKURL')),
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
var commonFormItems = [
|
var commonFormItems = [
|
||||||
[GeneratedFormSwitch('filterByLinkText', label: tr('filterByLinkText'))],
|
[GeneratedFormSwitch('filterByLinkText', label: tr('filterByLinkText'))],
|
||||||
@ -139,20 +137,72 @@ class HTML extends AppSource {
|
|||||||
],
|
],
|
||||||
finalStepFormitems[0],
|
finalStepFormitems[0],
|
||||||
...commonFormItems,
|
...commonFormItems,
|
||||||
...finalStepFormitems.sublist(1)
|
...finalStepFormitems.sublist(1),
|
||||||
|
[
|
||||||
|
GeneratedFormSubForm(
|
||||||
|
'requestHeader',
|
||||||
|
[
|
||||||
|
[
|
||||||
|
GeneratedFormTextField('requestHeader',
|
||||||
|
label: tr('requestHeader'),
|
||||||
|
required: false,
|
||||||
|
additionalValidators: [
|
||||||
|
(value) {
|
||||||
|
if ((value ?? 'empty:valid')
|
||||||
|
.split(':')
|
||||||
|
.map((e) => e.trim())
|
||||||
|
.where((e) => e.isNotEmpty)
|
||||||
|
.length <
|
||||||
|
2) {
|
||||||
|
return tr('invalidInput');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
],
|
||||||
|
label: tr('requestHeader'),
|
||||||
|
defaultValue: [
|
||||||
|
{
|
||||||
|
'requestHeader':
|
||||||
|
'User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
],
|
||||||
|
[
|
||||||
|
GeneratedFormDropdown(
|
||||||
|
'defaultPseudoVersioningMethod',
|
||||||
|
[
|
||||||
|
MapEntry('partialAPKHash', tr('partialAPKHash')),
|
||||||
|
MapEntry('APKLinkHash', tr('APKLinkHash'))
|
||||||
|
],
|
||||||
|
label: tr('defaultPseudoVersioningMethod'),
|
||||||
|
defaultValue: 'partialAPKHash')
|
||||||
|
]
|
||||||
];
|
];
|
||||||
overrideVersionDetectionFormDefault('noVersionDetection',
|
|
||||||
disableStandard: false, disableRelDate: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, String>?> getRequestHeaders(
|
Future<Map<String, String>?> getRequestHeaders(
|
||||||
{Map<String, dynamic> additionalSettings = const <String, dynamic>{},
|
Map<String, dynamic> additionalSettings,
|
||||||
bool forAPKDownload = false}) async {
|
{bool forAPKDownload = false}) async {
|
||||||
return {
|
if (additionalSettings.isNotEmpty) {
|
||||||
"User-Agent":
|
if (additionalSettings['requestHeader']?.isNotEmpty != true) {
|
||||||
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"
|
additionalSettings['requestHeader'] = [];
|
||||||
};
|
}
|
||||||
|
additionalSettings['requestHeader'] = additionalSettings['requestHeader']
|
||||||
|
.where((l) => l['requestHeader'].isNotEmpty == true)
|
||||||
|
.toList();
|
||||||
|
Map<String, String> requestHeaders = {};
|
||||||
|
for (int i = 0; i < (additionalSettings['requestHeader'].length); i++) {
|
||||||
|
var temp =
|
||||||
|
(additionalSettings['requestHeader'][i]['requestHeader'] as String)
|
||||||
|
.split(':');
|
||||||
|
requestHeaders[temp[0].trim()] = temp.sublist(1).join(':').trim();
|
||||||
|
}
|
||||||
|
return requestHeaders;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -233,7 +283,8 @@ class HTML extends AppSource {
|
|||||||
.where((l) => l['customLinkFilterRegex'].isNotEmpty == true)
|
.where((l) => l['customLinkFilterRegex'].isNotEmpty == true)
|
||||||
.toList();
|
.toList();
|
||||||
for (int i = 0; i < (additionalSettings['intermediateLink'].length); i++) {
|
for (int i = 0; i < (additionalSettings['intermediateLink'].length); i++) {
|
||||||
var intLinks = await grabLinksCommon(await sourceRequest(currentUrl),
|
var intLinks = await grabLinksCommon(
|
||||||
|
await sourceRequest(currentUrl, additionalSettings),
|
||||||
additionalSettings['intermediateLink'][i]);
|
additionalSettings['intermediateLink'][i]);
|
||||||
if (intLinks.isEmpty) {
|
if (intLinks.isEmpty) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
@ -241,30 +292,34 @@ class HTML extends AppSource {
|
|||||||
currentUrl = intLinks.last.key;
|
currentUrl = intLinks.last.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var uri = Uri.parse(currentUrl);
|
var uri = Uri.parse(currentUrl);
|
||||||
Response res = await sourceRequest(currentUrl);
|
List<MapEntry<String, String>> links = [];
|
||||||
var links = await grabLinksCommon(res, additionalSettings);
|
String versionExtractionWholePageString = currentUrl;
|
||||||
|
if (additionalSettings['directAPKLink'] != true) {
|
||||||
if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true) {
|
Response res = await sourceRequest(currentUrl, additionalSettings);
|
||||||
var reg = RegExp(additionalSettings['apkFilterRegEx']);
|
versionExtractionWholePageString =
|
||||||
links = links.where((element) => reg.hasMatch(element.key)).toList();
|
res.body.split('\r\n').join('\n').split('\n').join('\\n');
|
||||||
}
|
links = await grabLinksCommon(res, additionalSettings);
|
||||||
if (links.isEmpty) {
|
links = filterApks(links, additionalSettings['apkFilterRegEx'],
|
||||||
throw NoReleasesError();
|
additionalSettings['invertAPKFilter']);
|
||||||
|
if (links.isEmpty) {
|
||||||
|
throw NoReleasesError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
links = [MapEntry(currentUrl, currentUrl)];
|
||||||
}
|
}
|
||||||
var rel = links.last.key;
|
var rel = links.last.key;
|
||||||
String? version;
|
String? version;
|
||||||
if (additionalSettings['supportFixedAPKURL'] != true) {
|
|
||||||
version = rel.hashCode.toString();
|
|
||||||
}
|
|
||||||
version = extractVersion(
|
version = extractVersion(
|
||||||
additionalSettings['versionExtractionRegEx'] as String?,
|
additionalSettings['versionExtractionRegEx'] as String?,
|
||||||
additionalSettings['matchGroupToUse'] as String?,
|
additionalSettings['matchGroupToUse'] as String?,
|
||||||
additionalSettings['versionExtractWholePage'] == true
|
additionalSettings['versionExtractWholePage'] == true
|
||||||
? res.body.split('\r\n').join('\n').split('\n').join('\\n')
|
? versionExtractionWholePageString
|
||||||
: rel);
|
: rel);
|
||||||
version ??= (await checkDownloadHash(rel)).toString();
|
version ??=
|
||||||
|
additionalSettings['defaultPseudoVersioningMethod'] == 'APKLinkHash'
|
||||||
|
? rel.hashCode.toString()
|
||||||
|
: (await checkPartialDownloadHashDynamic(rel)).toString();
|
||||||
return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
|
return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
|
||||||
AppNames(uri.host, tr('app')));
|
AppNames(uri.host, tr('app')));
|
||||||
}
|
}
|
||||||
|
@ -6,26 +6,30 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
class HuaweiAppGallery extends AppSource {
|
class HuaweiAppGallery extends AppSource {
|
||||||
HuaweiAppGallery() {
|
HuaweiAppGallery() {
|
||||||
name = 'Huawei AppGallery';
|
name = 'Huawei AppGallery';
|
||||||
host = 'appgallery.huawei.com';
|
hosts = ['appgallery.huawei.com'];
|
||||||
overrideVersionDetectionFormDefault('releaseDateAsVersion',
|
versionDetectionDisallowed = true;
|
||||||
disableStandard: true);
|
showReleaseDateAsVersionToggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://(www\\.)?$host/app/[^/]+');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/app/[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDlUrl(String standardUrl) =>
|
getDlUrl(String standardUrl) =>
|
||||||
'https://${host!.replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}';
|
'https://${hosts[0].replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}';
|
||||||
|
|
||||||
requestAppdlRedirect(String dlUrl) async {
|
requestAppdlRedirect(
|
||||||
Response res = await sourceRequest(dlUrl, followRedirects: false);
|
String dlUrl, Map<String, dynamic> additionalSettings) async {
|
||||||
|
Response res =
|
||||||
|
await sourceRequest(dlUrl, additionalSettings, followRedirects: false);
|
||||||
if (res.statusCode == 200 ||
|
if (res.statusCode == 200 ||
|
||||||
res.statusCode == 302 ||
|
res.statusCode == 302 ||
|
||||||
res.statusCode == 304) {
|
res.statusCode == 304) {
|
||||||
@ -52,7 +56,7 @@ class HuaweiAppGallery extends AppSource {
|
|||||||
Future<String?> tryInferringAppId(String standardUrl,
|
Future<String?> tryInferringAppId(String standardUrl,
|
||||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||||
String dlUrl = getDlUrl(standardUrl);
|
String dlUrl = getDlUrl(standardUrl);
|
||||||
Response res = await requestAppdlRedirect(dlUrl);
|
Response res = await requestAppdlRedirect(dlUrl, additionalSettings);
|
||||||
return res.headers['location'] != null
|
return res.headers['location'] != null
|
||||||
? appIdFromRedirectDlUrl(res.headers['location']!)
|
? appIdFromRedirectDlUrl(res.headers['location']!)
|
||||||
: null;
|
: null;
|
||||||
@ -64,7 +68,7 @@ class HuaweiAppGallery extends AppSource {
|
|||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
String dlUrl = getDlUrl(standardUrl);
|
String dlUrl = getDlUrl(standardUrl);
|
||||||
Response res = await requestAppdlRedirect(dlUrl);
|
Response res = await requestAppdlRedirect(dlUrl, additionalSettings);
|
||||||
if (res.headers['location'] == null) {
|
if (res.headers['location'] == null) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ class IzzyOnDroid extends AppSource {
|
|||||||
late FDroid fd;
|
late FDroid fd;
|
||||||
|
|
||||||
IzzyOnDroid() {
|
IzzyOnDroid() {
|
||||||
host = 'izzysoft.de';
|
hosts = ['izzysoft.de'];
|
||||||
fd = FDroid();
|
fd = FDroid();
|
||||||
additionalSourceAppSpecificSettingFormItems =
|
additionalSourceAppSpecificSettingFormItems =
|
||||||
fd.additionalSourceAppSpecificSettingFormItems;
|
fd.additionalSourceAppSpecificSettingFormItems;
|
||||||
@ -15,17 +15,20 @@ class IzzyOnDroid extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegExA = RegExp('^https?://android.$host/repo/apk/[^/]+');
|
RegExp standardUrlRegExA = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegExA.firstMatch(url.toLowerCase());
|
'^https?://android.${getSourceRegex(hosts)}/repo/apk/[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegExA.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
RegExp standardUrlRegExB =
|
RegExp standardUrlRegExB = RegExp(
|
||||||
RegExp('^https?://apt.$host/fdroid/index/apk/[^/]+');
|
'^https?://apt.${getSourceRegex(hosts)}/fdroid/index/apk/[^/]+',
|
||||||
match = standardUrlRegExB.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
match = standardUrlRegExB.firstMatch(url);
|
||||||
}
|
}
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -42,14 +45,11 @@ class IzzyOnDroid extends AppSource {
|
|||||||
String? appId = await tryInferringAppId(standardUrl);
|
String? appId = await tryInferringAppId(standardUrl);
|
||||||
return fd.getAPKUrlsFromFDroidPackagesAPIResponse(
|
return fd.getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||||
await sourceRequest(
|
await sourceRequest(
|
||||||
'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'),
|
'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId',
|
||||||
|
additionalSettings),
|
||||||
'https://android.izzysoft.de/frepo/$appId',
|
'https://android.izzysoft.de/frepo/$appId',
|
||||||
standardUrl,
|
standardUrl,
|
||||||
name,
|
name,
|
||||||
autoSelectHighestVersionCode:
|
additionalSettings: additionalSettings);
|
||||||
additionalSettings['autoSelectHighestVersionCode'] == true,
|
|
||||||
trySelectingSuggestedVersionCode:
|
|
||||||
additionalSettings['trySelectingSuggestedVersionCode'] == true,
|
|
||||||
filterVersionsByRegEx: additionalSettings['filterVersionsByRegEx']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,9 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class Jenkins extends AppSource {
|
class Jenkins extends AppSource {
|
||||||
Jenkins() {
|
Jenkins() {
|
||||||
overrideVersionDetectionFormDefault('releaseDateAsVersion',
|
versionDetectionDisallowed = true;
|
||||||
disableStandard: true);
|
neverAutoSelect = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String trimJobUrl(String url) {
|
String trimJobUrl(String url) {
|
||||||
@ -16,7 +17,7 @@ class Jenkins extends AppSource {
|
|||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -29,8 +30,8 @@ class Jenkins extends AppSource {
|
|||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
standardUrl = trimJobUrl(standardUrl);
|
standardUrl = trimJobUrl(standardUrl);
|
||||||
Response res =
|
Response res = await sourceRequest(
|
||||||
await sourceRequest('$standardUrl/lastSuccessfulBuild/api/json');
|
'$standardUrl/lastSuccessfulBuild/api/json', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var json = jsonDecode(res.body);
|
var json = jsonDecode(res.body);
|
||||||
var releaseDate = json['timestamp'] == null
|
var releaseDate = json['timestamp'] == null
|
||||||
|
@ -6,17 +6,19 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class Mullvad extends AppSource {
|
class Mullvad extends AppSource {
|
||||||
Mullvad() {
|
Mullvad() {
|
||||||
host = 'mullvad.net';
|
hosts = ['mullvad.net'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://(www\\.)?$host');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://(www\\.)?${getSourceRegex(hosts)}',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -28,7 +30,8 @@ class Mullvad extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
Response res = await sourceRequest('$standardUrl/en/download/android');
|
Response res = await sourceRequest(
|
||||||
|
'$standardUrl/en/download/android', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var versions = parse(res.body)
|
var versions = parse(res.body)
|
||||||
.querySelectorAll('p')
|
.querySelectorAll('p')
|
||||||
|
@ -5,18 +5,20 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class NeutronCode extends AppSource {
|
class NeutronCode extends AppSource {
|
||||||
NeutronCode() {
|
NeutronCode() {
|
||||||
host = 'neutroncode.com';
|
hosts = ['neutroncode.com'];
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx =
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExp('^https?://(www\\.)?$host/downloads/file/[^/]+');
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/downloads/file/[^/]+',
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -79,7 +81,7 @@ class NeutronCode extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
Response res = await sourceRequest(standardUrl);
|
Response res = await sourceRequest(standardUrl, additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var http = parse(res.body);
|
var http = parse(res.body);
|
||||||
var name = http.querySelector('.pd-title')?.innerHtml;
|
var name = http.querySelector('.pd-title')?.innerHtml;
|
||||||
@ -92,7 +94,7 @@ class NeutronCode extends AppSource {
|
|||||||
if (version == null) {
|
if (version == null) {
|
||||||
throw NoVersionError();
|
throw NoVersionError();
|
||||||
}
|
}
|
||||||
String? apkUrl = 'https://$host/download/$filename';
|
String? apkUrl = 'https://${hosts[0]}/download/$filename';
|
||||||
var dateStringOriginal =
|
var dateStringOriginal =
|
||||||
http.querySelector('.pd-date-txt')?.nextElementSibling?.innerHtml;
|
http.querySelector('.pd-date-txt')?.nextElementSibling?.innerHtml;
|
||||||
var dateString = dateStringOriginal != null
|
var dateString = dateStringOriginal != null
|
||||||
|
@ -5,12 +5,12 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class Signal extends AppSource {
|
class Signal extends AppSource {
|
||||||
Signal() {
|
Signal() {
|
||||||
host = 'signal.org';
|
hosts = ['signal.org'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
return 'https://$host';
|
return 'https://${hosts[0]}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -18,8 +18,8 @@ class Signal extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
Response res =
|
Response res = await sourceRequest(
|
||||||
await sourceRequest('https://updates.$host/android/latest.json');
|
'https://updates.${hosts[0]}/android/latest.json', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var json = jsonDecode(res.body);
|
var json = jsonDecode(res.body);
|
||||||
String? apkUrl = json['url'];
|
String? apkUrl = json['url'];
|
||||||
|
@ -5,24 +5,34 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class SourceForge extends AppSource {
|
class SourceForge extends AppSource {
|
||||||
SourceForge() {
|
SourceForge() {
|
||||||
host = 'sourceforge.net';
|
hosts = ['sourceforge.net'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegExB = RegExp('^https?://(www\\.)?$host/p/[^/]+');
|
var sourceRegex = getSourceRegex(hosts);
|
||||||
RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase());
|
RegExp standardUrlRegExC =
|
||||||
|
RegExp('^https?://(www\\.)?$sourceRegex/p/.+', caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegExC.firstMatch(url);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
url =
|
url =
|
||||||
'https://${Uri.parse(url.substring(0, match.end)).host}/projects/${url.substring(Uri.parse(url.substring(0, match.end)).host.length + '/projects/'.length + 1)}';
|
'https://${Uri.parse(match.group(0)!).host}/projects/${url.substring(Uri.parse(match.group(0)!).host.length + '/projects/'.length + 1)}';
|
||||||
}
|
}
|
||||||
RegExp standardUrlRegExA =
|
RegExp standardUrlRegExB = RegExp(
|
||||||
RegExp('^https?://(www\\.)?$host/projects/[^/]+');
|
'^https?://(www\\.)?$sourceRegex/projects/[^/]+',
|
||||||
match = standardUrlRegExA.firstMatch(url.toLowerCase());
|
caseSensitive: false);
|
||||||
|
match = standardUrlRegExB.firstMatch(url);
|
||||||
|
if (match != null && match.group(0) == url) {
|
||||||
|
url = '$url/files';
|
||||||
|
}
|
||||||
|
RegExp standardUrlRegExA = RegExp(
|
||||||
|
'^https?://(www\\.)?$sourceRegex/projects/[^/]+/files(/.+)?',
|
||||||
|
caseSensitive: false);
|
||||||
|
match = standardUrlRegExA.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -30,37 +40,79 @@ class SourceForge extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
Response res = await sourceRequest('$standardUrl/rss?path=/');
|
var standardUri = Uri.parse(standardUrl);
|
||||||
|
if (standardUri.pathSegments.length == 2) {
|
||||||
|
standardUrl = '$standardUrl/files';
|
||||||
|
standardUri = Uri.parse(standardUrl);
|
||||||
|
}
|
||||||
|
Response res = await sourceRequest(
|
||||||
|
'${standardUri.origin}/${standardUri.pathSegments.sublist(0, 2).join('/')}/rss?path=/',
|
||||||
|
additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var parsedHtml = parse(res.body);
|
var parsedHtml = parse(res.body);
|
||||||
var allDownloadLinks =
|
var allDownloadLinks = parsedHtml
|
||||||
parsedHtml.querySelectorAll('guid').map((e) => e.innerHtml).toList();
|
.querySelectorAll('guid')
|
||||||
|
.map((e) => e.innerHtml)
|
||||||
|
.where((element) => element.startsWith(standardUrl))
|
||||||
|
.toList();
|
||||||
getVersion(String url) {
|
getVersion(String url) {
|
||||||
try {
|
try {
|
||||||
var tokens = url.split('/');
|
var segments = url
|
||||||
var fi = tokens.indexOf('files');
|
.substring(standardUrl.length)
|
||||||
return tokens[tokens[fi + 2] == 'download' ? fi - 1 : fi + 1];
|
.split('/')
|
||||||
|
.where((element) => element.isNotEmpty)
|
||||||
|
.toList()
|
||||||
|
.reversed
|
||||||
|
.toList()
|
||||||
|
.sublist(1)
|
||||||
|
.reversed
|
||||||
|
.toList();
|
||||||
|
segments = segments.length > 1
|
||||||
|
? segments.reversed.toList().sublist(1).reversed.toList()
|
||||||
|
: segments;
|
||||||
|
var version = segments.isNotEmpty ? segments.join('/') : null;
|
||||||
|
if (version != null) {
|
||||||
|
try {
|
||||||
|
var extractedVersion = extractVersion(
|
||||||
|
additionalSettings['versionExtractionRegEx'] as String?,
|
||||||
|
additionalSettings['matchGroupToUse'] as String?,
|
||||||
|
version);
|
||||||
|
if (extractedVersion != null) {
|
||||||
|
version = extractedVersion;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e is NoVersionError) {
|
||||||
|
version = null;
|
||||||
|
} else {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return version;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String? version = getVersion(allDownloadLinks[0]);
|
var apkUrlListAllReleases = allDownloadLinks
|
||||||
|
.where((element) => element.toLowerCase().endsWith('.apk/download'))
|
||||||
|
.where((element) => getVersion(element) != null)
|
||||||
|
.toList();
|
||||||
|
if (apkUrlListAllReleases.isEmpty) {
|
||||||
|
throw NoReleasesError();
|
||||||
|
}
|
||||||
|
String? version = getVersion(apkUrlListAllReleases[0]);
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
throw NoVersionError();
|
throw NoVersionError();
|
||||||
}
|
}
|
||||||
var apkUrlListAllReleases = allDownloadLinks
|
|
||||||
.where((element) => element.toLowerCase().endsWith('.apk/download'))
|
|
||||||
.toList();
|
|
||||||
var apkUrlList =
|
var apkUrlList =
|
||||||
apkUrlListAllReleases // This can be used skipped for fallback support later
|
apkUrlListAllReleases // This can be used skipped for fallback support later
|
||||||
.where((element) => getVersion(element) == version)
|
.where((element) => getVersion(element) == version)
|
||||||
.toList();
|
.toList();
|
||||||
return APKDetails(
|
var segments = standardUrl.split('/');
|
||||||
version,
|
return APKDetails(version, getApkUrlsFromUrls(apkUrlList),
|
||||||
getApkUrlsFromUrls(apkUrlList),
|
AppNames(name, segments[segments.indexOf('files') - 1]));
|
||||||
AppNames(
|
|
||||||
name, standardUrl.substring(standardUrl.lastIndexOf('/') + 1)));
|
|
||||||
} else {
|
} else {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,8 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
|
|
||||||
class SourceHut extends AppSource {
|
class SourceHut extends AppSource {
|
||||||
SourceHut() {
|
SourceHut() {
|
||||||
host = 'git.sr.ht';
|
hosts = ['git.sr.ht'];
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
|
|
||||||
additionalSourceAppSpecificSettingFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
@ -20,12 +21,14 @@ class SourceHut extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://(www\\.)?$host/[^/]+/[^/]+');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/[^/]+/[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return url.substring(0, match.end);
|
return match.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -36,11 +39,21 @@ class SourceHut extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
|
if (standardUrl.endsWith('/refs')) {
|
||||||
|
standardUrl = standardUrl
|
||||||
|
.split('/')
|
||||||
|
.reversed
|
||||||
|
.toList()
|
||||||
|
.sublist(1)
|
||||||
|
.reversed
|
||||||
|
.join('/');
|
||||||
|
}
|
||||||
Uri standardUri = Uri.parse(standardUrl);
|
Uri standardUri = Uri.parse(standardUrl);
|
||||||
String appName = standardUri.pathSegments.last;
|
String appName = standardUri.pathSegments.last;
|
||||||
bool fallbackToOlderReleases =
|
bool fallbackToOlderReleases =
|
||||||
additionalSettings['fallbackToOlderReleases'] == true;
|
additionalSettings['fallbackToOlderReleases'] == true;
|
||||||
Response res = await sourceRequest('$standardUrl/refs/rss.xml');
|
Response res =
|
||||||
|
await sourceRequest('$standardUrl/refs/rss.xml', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var parsedHtml = parse(res.body);
|
var parsedHtml = parse(res.body);
|
||||||
List<APKDetails> apkDetailsList = [];
|
List<APKDetails> apkDetailsList = [];
|
||||||
@ -69,7 +82,7 @@ class SourceHut extends AppSource {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
var res2 = await sourceRequest(releasePage);
|
var res2 = await sourceRequest(releasePage, additionalSettings);
|
||||||
List<MapEntry<String, String>> apkUrls = [];
|
List<MapEntry<String, String>> apkUrls = [];
|
||||||
if (res2.statusCode == 200) {
|
if (res2.statusCode == 200) {
|
||||||
apkUrls = getApkUrlsFromUrls(parse(res2.body)
|
apkUrls = getApkUrlsFromUrls(parse(res2.body)
|
||||||
|
@ -7,8 +7,8 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class SteamMobile extends AppSource {
|
class SteamMobile extends AppSource {
|
||||||
SteamMobile() {
|
SteamMobile() {
|
||||||
host = 'store.steampowered.com';
|
hosts = ['store.steampowered.com'];
|
||||||
name = tr('steam');
|
name = 'Steam';
|
||||||
additionalSourceAppSpecificSettingFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
GeneratedFormDropdown('app', apks.entries.toList(),
|
GeneratedFormDropdown('app', apks.entries.toList(),
|
||||||
@ -21,7 +21,7 @@ class SteamMobile extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
return 'https://$host';
|
return 'https://${hosts[0]}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -29,7 +29,8 @@ class SteamMobile extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
Response res = await sourceRequest('https://$host/mobile');
|
Response res =
|
||||||
|
await sourceRequest('https://${hosts[0]}/mobile', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var apkNamePrefix = additionalSettings['app'] as String?;
|
var apkNamePrefix = additionalSettings['app'] as String?;
|
||||||
if (apkNamePrefix == null) {
|
if (apkNamePrefix == null) {
|
||||||
|
@ -6,13 +6,13 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class TelegramApp extends AppSource {
|
class TelegramApp extends AppSource {
|
||||||
TelegramApp() {
|
TelegramApp() {
|
||||||
host = 'telegram.org';
|
hosts = ['telegram.org'];
|
||||||
name = 'Telegram ${tr('app')}';
|
name = 'Telegram ${tr('app')}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
return 'https://$host';
|
return 'https://${hosts[0]}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -20,7 +20,8 @@ class TelegramApp extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
Response res = await sourceRequest('https://t.me/s/TAndroidAPK');
|
Response res =
|
||||||
|
await sourceRequest('https://t.me/s/TAndroidAPK', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var http = parse(res.body);
|
var http = parse(res.body);
|
||||||
var messages =
|
var messages =
|
||||||
|
@ -6,29 +6,34 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class Uptodown extends AppSource {
|
class Uptodown extends AppSource {
|
||||||
Uptodown() {
|
Uptodown() {
|
||||||
host = 'uptodown.com';
|
hosts = ['uptodown.com'];
|
||||||
allowSubDomains = true;
|
allowSubDomains = true;
|
||||||
naiveStandardVersionDetection = true;
|
naiveStandardVersionDetection = true;
|
||||||
|
showReleaseDateAsVersionToggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('^https?://([^\\.]+\\.){2,}$host');
|
RegExp standardUrlRegEx = RegExp(
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
'^https?://([^\\.]+\\.){2,}${getSourceRegex(hosts)}',
|
||||||
|
caseSensitive: false);
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw InvalidURLError(name);
|
throw InvalidURLError(name);
|
||||||
}
|
}
|
||||||
return '${url.substring(0, match.end)}/android/download';
|
return '${match.group(0)!}/android/download';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String?> tryInferringAppId(String standardUrl,
|
Future<String?> tryInferringAppId(String standardUrl,
|
||||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||||
return (await getAppDetailsFromPage(standardUrl))['appId'];
|
return (await getAppDetailsFromPage(
|
||||||
|
standardUrl, additionalSettings))['appId'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, String?>> getAppDetailsFromPage(String standardUrl) async {
|
Future<Map<String, String?>> getAppDetailsFromPage(
|
||||||
var res = await sourceRequest(standardUrl);
|
String standardUrl, Map<String, dynamic> additionalSettings) async {
|
||||||
|
var res = await sourceRequest(standardUrl, additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
@ -56,7 +61,8 @@ class Uptodown extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
var appDetails = await getAppDetailsFromPage(standardUrl);
|
var appDetails =
|
||||||
|
await getAppDetailsFromPage(standardUrl, additionalSettings);
|
||||||
var version = appDetails['version'];
|
var version = appDetails['version'];
|
||||||
var apkUrl = appDetails['apkUrl'];
|
var apkUrl = appDetails['apkUrl'];
|
||||||
var appId = appDetails['appId'];
|
var appId = appDetails['appId'];
|
||||||
@ -82,9 +88,9 @@ class Uptodown extends AppSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> apkUrlPrefetchModifier(
|
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
|
||||||
String apkUrl, String standardUrl) async {
|
Map<String, dynamic> additionalSettings) async {
|
||||||
var res = await sourceRequest(apkUrl);
|
var res = await sourceRequest(apkUrl, additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
@ -94,6 +100,6 @@ class Uptodown extends AppSource {
|
|||||||
if (finalUrlKey == null) {
|
if (finalUrlKey == null) {
|
||||||
throw NoAPKError();
|
throw NoAPKError();
|
||||||
}
|
}
|
||||||
return 'https://dw.$host/dwn/$finalUrlKey';
|
return 'https://dw.${hosts[0]}/dwn/$finalUrlKey';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,33 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:obtainium/app_sources/html.dart';
|
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
class VLC extends AppSource {
|
class VLC extends AppSource {
|
||||||
VLC() {
|
VLC() {
|
||||||
host = 'videolan.org';
|
hosts = ['videolan.org'];
|
||||||
}
|
}
|
||||||
get dwUrlBase => 'https://get.$host/vlc-android/';
|
get dwUrlBase => 'https://get.${hosts[0]}/vlc-android/';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, String>?> getRequestHeaders(
|
Future<Map<String, String>?> getRequestHeaders(
|
||||||
{Map<String, dynamic> additionalSettings = const <String, dynamic>{},
|
Map<String, dynamic> additionalSettings,
|
||||||
bool forAPKDownload = false}) =>
|
{bool forAPKDownload = false}) async {
|
||||||
HTML().getRequestHeaders(
|
return {
|
||||||
additionalSettings: additionalSettings,
|
"User-Agent":
|
||||||
forAPKDownload: forAPKDownload);
|
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
return 'https://$host';
|
return 'https://${hosts[0]}';
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getLatestVersion(String standardUrl) async {
|
Future<String?> getLatestVersion(
|
||||||
Response res = await sourceRequest(dwUrlBase);
|
String standardUrl, Map<String, dynamic> additionalSettings) async {
|
||||||
|
Response res = await sourceRequest(dwUrlBase, additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var dwLinks = parse(res.body)
|
var dwLinks = parse(res.body)
|
||||||
.querySelectorAll('a')
|
.querySelectorAll('a')
|
||||||
@ -77,9 +79,9 @@ class VLC extends AppSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> apkUrlPrefetchModifier(
|
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
|
||||||
String apkUrl, String standardUrl) async {
|
Map<String, dynamic> additionalSettings) async {
|
||||||
Response res = await sourceRequest(apkUrl);
|
Response res = await sourceRequest(apkUrl, additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
String? apkUrl =
|
String? apkUrl =
|
||||||
parse(res.body).querySelector('#alt_link')?.attributes['href'];
|
parse(res.body).querySelector('#alt_link')?.attributes['href'];
|
||||||
|
@ -5,20 +5,20 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class WhatsApp extends AppSource {
|
class WhatsApp extends AppSource {
|
||||||
WhatsApp() {
|
WhatsApp() {
|
||||||
host = 'whatsapp.com';
|
hosts = ['whatsapp.com'];
|
||||||
overrideVersionDetectionFormDefault('noVersionDetection',
|
versionDetectionDisallowed = true;
|
||||||
disableStandard: true, disableRelDate: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
return 'https://$host';
|
return 'https://${hosts[0]}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> apkUrlPrefetchModifier(
|
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
|
||||||
String apkUrl, String standardUrl) async {
|
Map<String, dynamic> additionalSettings) async {
|
||||||
Response res = await sourceRequest('$standardUrl/android');
|
Response res =
|
||||||
|
await sourceRequest('$standardUrl/android', additionalSettings);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var targetLinks = parse(res.body)
|
var targetLinks = parse(res.body)
|
||||||
.querySelectorAll('a')
|
.querySelectorAll('a')
|
||||||
@ -42,8 +42,8 @@ class WhatsApp extends AppSource {
|
|||||||
) async {
|
) async {
|
||||||
// This is a CDN link that is consistent per version
|
// This is a CDN link that is consistent per version
|
||||||
// But it has query params that change constantly
|
// But it has query params that change constantly
|
||||||
Uri apkUri =
|
Uri apkUri = Uri.parse(await apkUrlPrefetchModifier(
|
||||||
Uri.parse(await apkUrlPrefetchModifier(standardUrl, standardUrl));
|
standardUrl, standardUrl, additionalSettings));
|
||||||
var unusableApkUrl = '${apkUri.origin}/${apkUri.path}';
|
var unusableApkUrl = '${apkUri.origin}/${apkUri.path}';
|
||||||
// So we use the param-less URL is a pseudo-version to add the app and check for updates
|
// So we use the param-less URL is a pseudo-version to add the app and check for updates
|
||||||
// See #357 for why we can't scrape the version number directly
|
// See #357 for why we can't scrape the version number directly
|
||||||
|
@ -13,6 +13,7 @@ abstract class GeneratedFormItem {
|
|||||||
late dynamic defaultValue;
|
late dynamic defaultValue;
|
||||||
List<dynamic> additionalValidators;
|
List<dynamic> additionalValidators;
|
||||||
dynamic ensureType(dynamic val);
|
dynamic ensureType(dynamic val);
|
||||||
|
GeneratedFormItem clone();
|
||||||
|
|
||||||
GeneratedFormItem(this.key,
|
GeneratedFormItem(this.key,
|
||||||
{this.label = 'Input',
|
{this.label = 'Input',
|
||||||
@ -44,6 +45,20 @@ class GeneratedFormTextField extends GeneratedFormItem {
|
|||||||
String ensureType(val) {
|
String ensureType(val) {
|
||||||
return val.toString();
|
return val.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GeneratedFormTextField clone() {
|
||||||
|
return GeneratedFormTextField(key,
|
||||||
|
label: label,
|
||||||
|
belowWidgets: belowWidgets,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
additionalValidators: List.from(additionalValidators),
|
||||||
|
required: required,
|
||||||
|
max: max,
|
||||||
|
hint: hint,
|
||||||
|
password: password,
|
||||||
|
textInputType: textInputType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratedFormDropdown extends GeneratedFormItem {
|
class GeneratedFormDropdown extends GeneratedFormItem {
|
||||||
@ -64,14 +79,31 @@ class GeneratedFormDropdown extends GeneratedFormItem {
|
|||||||
String ensureType(val) {
|
String ensureType(val) {
|
||||||
return val.toString();
|
return val.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GeneratedFormDropdown clone() {
|
||||||
|
return GeneratedFormDropdown(
|
||||||
|
key,
|
||||||
|
opts?.map((e) => MapEntry(e.key, e.value)).toList(),
|
||||||
|
label: label,
|
||||||
|
belowWidgets: belowWidgets,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
disabledOptKeys:
|
||||||
|
disabledOptKeys != null ? List.from(disabledOptKeys!) : null,
|
||||||
|
additionalValidators: List.from(additionalValidators),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratedFormSwitch extends GeneratedFormItem {
|
class GeneratedFormSwitch extends GeneratedFormItem {
|
||||||
|
bool disabled = false;
|
||||||
|
|
||||||
GeneratedFormSwitch(
|
GeneratedFormSwitch(
|
||||||
super.key, {
|
super.key, {
|
||||||
super.label,
|
super.label,
|
||||||
super.belowWidgets,
|
super.belowWidgets,
|
||||||
bool super.defaultValue = false,
|
bool super.defaultValue = false,
|
||||||
|
bool disabled = false,
|
||||||
List<String? Function(bool value)> super.additionalValidators = const [],
|
List<String? Function(bool value)> super.additionalValidators = const [],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,6 +111,16 @@ class GeneratedFormSwitch extends GeneratedFormItem {
|
|||||||
bool ensureType(val) {
|
bool ensureType(val) {
|
||||||
return val == true || val == 'true';
|
return val == true || val == 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GeneratedFormSwitch clone() {
|
||||||
|
return GeneratedFormSwitch(key,
|
||||||
|
label: label,
|
||||||
|
belowWidgets: belowWidgets,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
disabled: false,
|
||||||
|
additionalValidators: List.from(additionalValidators));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratedFormTagInput extends GeneratedFormItem {
|
class GeneratedFormTagInput extends GeneratedFormItem {
|
||||||
@ -103,6 +145,20 @@ class GeneratedFormTagInput extends GeneratedFormItem {
|
|||||||
Map<String, MapEntry<int, bool>> ensureType(val) {
|
Map<String, MapEntry<int, bool>> ensureType(val) {
|
||||||
return val is Map<String, MapEntry<int, bool>> ? val : {};
|
return val is Map<String, MapEntry<int, bool>> ? val : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GeneratedFormTagInput clone() {
|
||||||
|
return GeneratedFormTagInput(key,
|
||||||
|
label: label,
|
||||||
|
belowWidgets: belowWidgets,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
additionalValidators: List.from(additionalValidators),
|
||||||
|
deleteConfirmationMessage: deleteConfirmationMessage,
|
||||||
|
singleSelect: singleSelect,
|
||||||
|
alignment: alignment,
|
||||||
|
emptyMessage: emptyMessage,
|
||||||
|
showLabelWhenNotEmpty: showLabelWhenNotEmpty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef OnValueChanges = void Function(
|
typedef OnValueChanges = void Function(
|
||||||
@ -119,6 +175,19 @@ class GeneratedForm extends StatefulWidget {
|
|||||||
State<GeneratedForm> createState() => _GeneratedFormState();
|
State<GeneratedForm> createState() => _GeneratedFormState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<List<GeneratedFormItem>> cloneFormItems(
|
||||||
|
List<List<GeneratedFormItem>> items) {
|
||||||
|
List<List<GeneratedFormItem>> clonedItems = [];
|
||||||
|
for (var row in items) {
|
||||||
|
List<GeneratedFormItem> clonedRow = [];
|
||||||
|
for (var it in row) {
|
||||||
|
clonedRow.add(it.clone());
|
||||||
|
}
|
||||||
|
clonedItems.add(clonedRow);
|
||||||
|
}
|
||||||
|
return clonedItems;
|
||||||
|
}
|
||||||
|
|
||||||
class GeneratedFormSubForm extends GeneratedFormItem {
|
class GeneratedFormSubForm extends GeneratedFormItem {
|
||||||
final List<List<GeneratedFormItem>> items;
|
final List<List<GeneratedFormItem>> items;
|
||||||
|
|
||||||
@ -129,6 +198,12 @@ class GeneratedFormSubForm extends GeneratedFormItem {
|
|||||||
ensureType(val) {
|
ensureType(val) {
|
||||||
return val; // Not easy to validate List<Map<String, dynamic>>
|
return val; // Not easy to validate List<Map<String, dynamic>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GeneratedFormSubForm clone() {
|
||||||
|
return GeneratedFormSubForm(key, cloneFormItems(items),
|
||||||
|
label: label, belowWidgets: belowWidgets, defaultValue: defaultValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates a color in the HSLuv (Pastel) color space
|
// Generates a color in the HSLuv (Pastel) color space
|
||||||
@ -297,15 +372,51 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
|||||||
),
|
),
|
||||||
Switch(
|
Switch(
|
||||||
value: values[fieldKey],
|
value: values[fieldKey],
|
||||||
onChanged: (value) {
|
onChanged:
|
||||||
setState(() {
|
(widget.items[r][e] as GeneratedFormSwitch).disabled
|
||||||
values[fieldKey] = value;
|
? null
|
||||||
someValueChanged();
|
: (value) {
|
||||||
});
|
setState(() {
|
||||||
})
|
values[fieldKey] = value;
|
||||||
|
someValueChanged();
|
||||||
|
});
|
||||||
|
})
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else if (widget.items[r][e] is GeneratedFormTagInput) {
|
} else if (widget.items[r][e] is GeneratedFormTagInput) {
|
||||||
|
onAddPressed() {
|
||||||
|
showDialog<Map<String, dynamic>?>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext ctx) {
|
||||||
|
return GeneratedFormModal(
|
||||||
|
title: widget.items[r][e].label,
|
||||||
|
items: [
|
||||||
|
[GeneratedFormTextField('label', label: tr('label'))]
|
||||||
|
]);
|
||||||
|
}).then((value) {
|
||||||
|
String? label = value?['label'];
|
||||||
|
if (label != null) {
|
||||||
|
setState(() {
|
||||||
|
var temp =
|
||||||
|
values[fieldKey] as Map<String, MapEntry<int, bool>>?;
|
||||||
|
temp ??= {};
|
||||||
|
if (temp[label] == null) {
|
||||||
|
var singleSelect =
|
||||||
|
(widget.items[r][e] as GeneratedFormTagInput)
|
||||||
|
.singleSelect;
|
||||||
|
var someSelected = temp.entries
|
||||||
|
.where((element) => element.value.value)
|
||||||
|
.isNotEmpty;
|
||||||
|
temp[label] = MapEntry(generateRandomLightColor().value,
|
||||||
|
!(someSelected && singleSelect));
|
||||||
|
values[fieldKey] = temp;
|
||||||
|
someValueChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
formInputs[r][e] =
|
formInputs[r][e] =
|
||||||
Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
||||||
if ((values[fieldKey] as Map<String, MapEntry<int, bool>>?)
|
if ((values[fieldKey] as Map<String, MapEntry<int, bool>>?)
|
||||||
@ -331,14 +442,14 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
|||||||
(widget.items[r][e] as GeneratedFormTagInput).alignment,
|
(widget.items[r][e] as GeneratedFormTagInput).alignment,
|
||||||
crossAxisAlignment: WrapCrossAlignment.center,
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
(values[fieldKey] as Map<String, MapEntry<int, bool>>?)
|
// (values[fieldKey] as Map<String, MapEntry<int, bool>>?)
|
||||||
?.isEmpty ==
|
// ?.isEmpty ==
|
||||||
true
|
// true
|
||||||
? Text(
|
// ? Text(
|
||||||
(widget.items[r][e] as GeneratedFormTagInput)
|
// (widget.items[r][e] as GeneratedFormTagInput)
|
||||||
.emptyMessage,
|
// .emptyMessage,
|
||||||
)
|
// )
|
||||||
: const SizedBox.shrink(),
|
// : const SizedBox.shrink(),
|
||||||
...(values[fieldKey] as Map<String, MapEntry<int, bool>>?)
|
...(values[fieldKey] as Map<String, MapEntry<int, bool>>?)
|
||||||
?.entries
|
?.entries
|
||||||
.map((e2) {
|
.map((e2) {
|
||||||
@ -462,62 +573,37 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
|||||||
tooltip: tr('remove'),
|
tooltip: tr('remove'),
|
||||||
))
|
))
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
Padding(
|
(values[fieldKey] as Map<String, MapEntry<int, bool>>?)
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
?.isEmpty ==
|
||||||
child: IconButton(
|
true
|
||||||
onPressed: () {
|
? Padding(
|
||||||
showDialog<Map<String, dynamic>?>(
|
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
context: context,
|
child: TextButton.icon(
|
||||||
builder: (BuildContext ctx) {
|
onPressed: onAddPressed,
|
||||||
return GeneratedFormModal(
|
icon: const Icon(Icons.add),
|
||||||
title: widget.items[r][e].label,
|
label: Text(
|
||||||
items: [
|
(widget.items[r][e] as GeneratedFormTagInput)
|
||||||
[
|
.label),
|
||||||
GeneratedFormTextField('label',
|
))
|
||||||
label: tr('label'))
|
: Padding(
|
||||||
]
|
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
]);
|
child: IconButton(
|
||||||
}).then((value) {
|
onPressed: onAddPressed,
|
||||||
String? label = value?['label'];
|
icon: const Icon(Icons.add),
|
||||||
if (label != null) {
|
visualDensity: VisualDensity.compact,
|
||||||
setState(() {
|
tooltip: tr('add'),
|
||||||
var temp = values[fieldKey]
|
)),
|
||||||
as Map<String, MapEntry<int, bool>>?;
|
|
||||||
temp ??= {};
|
|
||||||
if (temp[label] == null) {
|
|
||||||
var singleSelect = (widget.items[r][e]
|
|
||||||
as GeneratedFormTagInput)
|
|
||||||
.singleSelect;
|
|
||||||
var someSelected = temp.entries
|
|
||||||
.where((element) => element.value.value)
|
|
||||||
.isNotEmpty;
|
|
||||||
temp[label] = MapEntry(
|
|
||||||
generateRandomLightColor().value,
|
|
||||||
!(someSelected && singleSelect));
|
|
||||||
values[fieldKey] = temp;
|
|
||||||
someValueChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.add),
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
tooltip: tr('add'),
|
|
||||||
)),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
} else if (widget.items[r][e] is GeneratedFormSubForm) {
|
} else if (widget.items[r][e] is GeneratedFormSubForm) {
|
||||||
List<Widget> subformColumn = [];
|
List<Widget> subformColumn = [];
|
||||||
|
var compact = (widget.items[r][e] as GeneratedFormSubForm)
|
||||||
|
.items
|
||||||
|
.length ==
|
||||||
|
1 &&
|
||||||
|
(widget.items[r][e] as GeneratedFormSubForm).items[0].length == 1;
|
||||||
for (int i = 0; i < values[fieldKey].length; i++) {
|
for (int i = 0; i < values[fieldKey].length; i++) {
|
||||||
var items = (widget.items[r][e] as GeneratedFormSubForm)
|
|
||||||
.items
|
|
||||||
.map((x) => x.map((y) {
|
|
||||||
y.defaultValue = values[fieldKey]?[i]?[y.key];
|
|
||||||
return y;
|
|
||||||
}).toList())
|
|
||||||
.toList();
|
|
||||||
var internalFormKey = ValueKey(generateRandomNumber(
|
var internalFormKey = ValueKey(generateRandomNumber(
|
||||||
values[fieldKey].length,
|
values[fieldKey].length,
|
||||||
seed2: i,
|
seed2: i,
|
||||||
@ -525,18 +611,28 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
|||||||
subformColumn.add(Column(
|
subformColumn.add(Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Divider(),
|
if (!compact)
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
Text(
|
if (!compact)
|
||||||
'${(widget.items[r][e] as GeneratedFormSubForm).label} (${i + 1})',
|
Text(
|
||||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
'${(widget.items[r][e] as GeneratedFormSubForm).label} (${i + 1})',
|
||||||
),
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
GeneratedForm(
|
GeneratedForm(
|
||||||
key: internalFormKey,
|
key: internalFormKey,
|
||||||
items: items,
|
items: cloneFormItems(
|
||||||
|
(widget.items[r][e] as GeneratedFormSubForm).items)
|
||||||
|
.map((x) => x.map((y) {
|
||||||
|
y.defaultValue = values[fieldKey]?[i]?[y.key];
|
||||||
|
y.key = '${y.key.toString()},$internalFormKey';
|
||||||
|
return y;
|
||||||
|
}).toList())
|
||||||
|
.toList(),
|
||||||
onValueChanges: (values, valid, isBuilding) {
|
onValueChanges: (values, valid, isBuilding) {
|
||||||
|
values = values.map(
|
||||||
|
(key, value) => MapEntry(key.split(',')[0], value));
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.values[fieldKey]?[i] = values;
|
this.values[fieldKey]?[i] = values;
|
||||||
}
|
}
|
||||||
@ -567,13 +663,12 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
|||||||
Icons.delete_outline_rounded,
|
Icons.delete_outline_rounded,
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
subformColumn.add(Padding(
|
subformColumn.add(Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: const EdgeInsets.only(bottom: 0, top: 8),
|
||||||
bottom: values[fieldKey].length > 0 ? 24 : 0, top: 8),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -591,9 +686,6 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
if (values[fieldKey].length > 0) {
|
|
||||||
subformColumn.add(const Divider());
|
|
||||||
}
|
|
||||||
formInputs[r][e] = Column(children: subformColumn);
|
formInputs[r][e] = Column(children: subformColumn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,6 @@ import 'package:easy_localization/src/easy_localization_controller.dart';
|
|||||||
// ignore: implementation_imports
|
// ignore: implementation_imports
|
||||||
import 'package:easy_localization/src/localization.dart';
|
import 'package:easy_localization/src/localization.dart';
|
||||||
|
|
||||||
const String currentVersion = '0.15.6';
|
|
||||||
const String currentReleaseTag =
|
|
||||||
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
|
|
||||||
|
|
||||||
const int bgUpdateCheckAlarmId = 666;
|
|
||||||
|
|
||||||
List<MapEntry<Locale, String>> supportedLocales = const [
|
List<MapEntry<Locale, String>> supportedLocales = const [
|
||||||
MapEntry(Locale('en'), 'English'),
|
MapEntry(Locale('en'), 'English'),
|
||||||
MapEntry(Locale('zh'), '简体中文'),
|
MapEntry(Locale('zh'), '简体中文'),
|
||||||
@ -146,6 +140,7 @@ class _ObtainiumState extends State<Obtainium> {
|
|||||||
BackgroundFetchConfig(
|
BackgroundFetchConfig(
|
||||||
minimumFetchInterval: 15,
|
minimumFetchInterval: 15,
|
||||||
stopOnTerminate: false,
|
stopOnTerminate: false,
|
||||||
|
startOnBoot: true,
|
||||||
enableHeadless: true,
|
enableHeadless: true,
|
||||||
requiresBatteryNotLow: false,
|
requiresBatteryNotLow: false,
|
||||||
requiresCharging: false,
|
requiresCharging: false,
|
||||||
@ -176,20 +171,30 @@ class _ObtainiumState extends State<Obtainium> {
|
|||||||
// If this is the first run, ask for notification permissions and add Obtainium to the Apps list
|
// If this is the first run, ask for notification permissions and add Obtainium to the Apps list
|
||||||
Permission.notification.request();
|
Permission.notification.request();
|
||||||
if (!fdroid) {
|
if (!fdroid) {
|
||||||
appsProvider.saveApps([
|
getInstalledInfo(obtainiumId).then((value) {
|
||||||
App(
|
if (value?.versionName != null) {
|
||||||
obtainiumId,
|
appsProvider.saveApps([
|
||||||
'https://github.com/ImranR98/Obtainium',
|
App(
|
||||||
'ImranR98',
|
obtainiumId,
|
||||||
'Obtainium',
|
obtainiumUrl,
|
||||||
currentReleaseTag,
|
'ImranR98',
|
||||||
currentReleaseTag,
|
'Obtainium',
|
||||||
[],
|
value!.versionName,
|
||||||
0,
|
value.versionName!,
|
||||||
{'includePrereleases': true},
|
[],
|
||||||
null,
|
0,
|
||||||
false)
|
{
|
||||||
], onlyIfExists: false);
|
'versionDetection': true,
|
||||||
|
'apkFilterRegEx': 'fdroid',
|
||||||
|
'invertAPKFilter': true
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
false)
|
||||||
|
], onlyIfExists: false);
|
||||||
|
}
|
||||||
|
}).catchError((err) {
|
||||||
|
print(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!supportedLocales
|
if (!supportedLocales
|
||||||
|
@ -18,7 +18,7 @@ class GitHubStars implements MassAppUrlSource {
|
|||||||
Response res = await get(
|
Response res = await get(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
'https://api.github.com/users/$username/starred?per_page=100&page=$page'),
|
'https://api.github.com/users/$username/starred?per_page=100&page=$page'),
|
||||||
headers: await GitHub().getRequestHeaders());
|
headers: await GitHub().getRequestHeaders({}));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
Map<String, List<String>> urlsWithDescriptions = {};
|
Map<String, List<String>> urlsWithDescriptions = {};
|
||||||
for (var e in (jsonDecode(res.body) as List<dynamic>)) {
|
for (var e in (jsonDecode(res.body) as List<dynamic>)) {
|
||||||
|
@ -59,7 +59,9 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
if (updateUrlInput) {
|
if (updateUrlInput) {
|
||||||
urlInputKey++;
|
urlInputKey++;
|
||||||
}
|
}
|
||||||
var prevHost = pickedSource?.host;
|
var prevHost = pickedSource?.hosts.isNotEmpty == true
|
||||||
|
? pickedSource?.hosts[0]
|
||||||
|
: null;
|
||||||
try {
|
try {
|
||||||
var naturalSource =
|
var naturalSource =
|
||||||
valid ? sourceProvider.getSource(userInput) : null;
|
valid ? sourceProvider.getSource(userInput) : null;
|
||||||
@ -77,7 +79,7 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
overrideSource: pickedSourceOverride)
|
overrideSource: pickedSourceOverride)
|
||||||
: null;
|
: null;
|
||||||
if (pickedSource.runtimeType != source.runtimeType ||
|
if (pickedSource.runtimeType != source.runtimeType ||
|
||||||
(prevHost != null && prevHost != source?.host)) {
|
(prevHost != null && prevHost != source?.hosts[0])) {
|
||||||
pickedSource = source;
|
pickedSource = source;
|
||||||
additionalSettings = source != null
|
additionalSettings = source != null
|
||||||
? getDefaultValuesFromFormItems(
|
? getDefaultValuesFromFormItems(
|
||||||
@ -133,8 +135,7 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
|
|
||||||
getReleaseDateAsVersionConfirmationIfNeeded(
|
getReleaseDateAsVersionConfirmationIfNeeded(
|
||||||
bool userPickedTrackOnly) async {
|
bool userPickedTrackOnly) async {
|
||||||
return (!(additionalSettings['versionDetection'] ==
|
return (!(additionalSettings['releaseDateAsVersion'] == true &&
|
||||||
'releaseDateAsVersion' &&
|
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
await showDialog(
|
await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@ -162,7 +163,7 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
app = await sourceProvider.getApp(
|
app = await sourceProvider.getApp(
|
||||||
pickedSource!, userInput.trim(), additionalSettings,
|
pickedSource!, userInput.trim(), additionalSettings,
|
||||||
trackOnlyOverride: trackOnly,
|
trackOnlyOverride: trackOnly,
|
||||||
overrideSource: pickedSourceOverride,
|
sourceIsOverriden: pickedSourceOverride != null,
|
||||||
inferAppIdIfOptional: inferAppIdIfOptional);
|
inferAppIdIfOptional: inferAppIdIfOptional);
|
||||||
// Only download the APK here if you need to for the package ID
|
// Only download the APK here if you need to for the package ID
|
||||||
if (isTempId(app) && app.additionalSettings['trackOnly'] != true) {
|
if (isTempId(app) && app.additionalSettings['trackOnly'] != true) {
|
||||||
@ -190,8 +191,7 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
throw ObtainiumError(tr('appAlreadyAdded'));
|
throw ObtainiumError(tr('appAlreadyAdded'));
|
||||||
}
|
}
|
||||||
if (app.additionalSettings['trackOnly'] == true ||
|
if (app.additionalSettings['trackOnly'] == true ||
|
||||||
app.additionalSettings['versionDetection'] !=
|
app.additionalSettings['versionDetection'] != true) {
|
||||||
'standardVersionDetection') {
|
|
||||||
app.installedVersion = app.latestVersion;
|
app.installedVersion = app.latestVersion;
|
||||||
}
|
}
|
||||||
app.categories = pickedCategories;
|
app.categories = pickedCategories;
|
||||||
@ -496,36 +496,74 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget getSourcesListWidget() => Column(
|
Widget getSourcesListWidget() => Padding(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
padding: const EdgeInsets.all(16),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
GestureDetector(
|
||||||
tr('supportedSources'),
|
onTap: () {
|
||||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
showDialog(
|
||||||
),
|
context: context,
|
||||||
const SizedBox(
|
builder: (context) {
|
||||||
height: 16,
|
return GeneratedFormModal(
|
||||||
),
|
singleNullReturnButton: tr('ok'),
|
||||||
...sourceProvider.sources.map((e) => GestureDetector(
|
title: tr('supportedSources'),
|
||||||
onTap: e.host != null
|
items: const [],
|
||||||
? () {
|
additionalWidgets: [
|
||||||
launchUrlString('https://${e.host}',
|
...sourceProvider.sources.map(
|
||||||
mode: LaunchMode.externalApplication);
|
(e) => Padding(
|
||||||
}
|
padding:
|
||||||
: null,
|
const EdgeInsets.symmetric(vertical: 4),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: e.hosts.isNotEmpty
|
||||||
|
? () {
|
||||||
|
launchUrlString(
|
||||||
|
'https://${e.hosts[0]}',
|
||||||
|
mode: LaunchMode
|
||||||
|
.externalApplication);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: Text(
|
||||||
|
'${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}',
|
||||||
|
style: TextStyle(
|
||||||
|
decoration: e.hosts.isNotEmpty
|
||||||
|
? TextDecoration.underline
|
||||||
|
: TextDecoration.none),
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${tr('note')}:',
|
||||||
|
style:
|
||||||
|
const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 4,
|
||||||
|
),
|
||||||
|
Text(tr('selfHostedNote',
|
||||||
|
args: [tr('overrideSource')])),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}',
|
tr('supportedSources'),
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
decoration: e.host != null
|
fontWeight: FontWeight.bold,
|
||||||
? TextDecoration.underline
|
decoration: TextDecoration.underline,
|
||||||
: TextDecoration.none,
|
|
||||||
fontStyle: FontStyle.italic),
|
fontStyle: FontStyle.italic),
|
||||||
)))
|
))
|
||||||
]);
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
|
bottomNavigationBar:
|
||||||
|
pickedSource == null ? getSourcesListWidget() : null,
|
||||||
body: CustomScrollView(shrinkWrap: true, slivers: <Widget>[
|
body: CustomScrollView(shrinkWrap: true, slivers: <Widget>[
|
||||||
CustomAppBar(title: tr('addApp')),
|
CustomAppBar(title: tr('addApp')),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
@ -557,18 +595,7 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
: const SizedBox();
|
: const SizedBox();
|
||||||
},
|
},
|
||||||
future: pickedSource?.getSourceNote()),
|
future: pickedSource?.getSourceNote()),
|
||||||
SizedBox(
|
|
||||||
height: pickedSource != null ? 16 : 96,
|
|
||||||
),
|
|
||||||
if (pickedSource != null) getAdditionalOptsCol(),
|
if (pickedSource != null) getAdditionalOptsCol(),
|
||||||
if (pickedSource == null)
|
|
||||||
const Divider(
|
|
||||||
height: 48,
|
|
||||||
),
|
|
||||||
if (pickedSource == null) getSourcesListWidget(),
|
|
||||||
SizedBox(
|
|
||||||
height: pickedSource != null ? 8 : 2,
|
|
||||||
),
|
|
||||||
])),
|
])),
|
||||||
)
|
)
|
||||||
]));
|
]));
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:obtainium/components/generated_form.dart';
|
|
||||||
import 'package:obtainium/components/generated_form_modal.dart';
|
import 'package:obtainium/components/generated_form_modal.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/main.dart';
|
import 'package:obtainium/main.dart';
|
||||||
@ -24,16 +23,35 @@ class AppPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _AppPageState extends State<AppPage> {
|
class _AppPageState extends State<AppPage> {
|
||||||
AppInMemory? prevApp;
|
AppInMemory? prevApp;
|
||||||
|
bool updating = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var appsProvider = context.watch<AppsProvider>();
|
var appsProvider = context.watch<AppsProvider>();
|
||||||
var settingsProvider = context.watch<SettingsProvider>();
|
var settingsProvider = context.watch<SettingsProvider>();
|
||||||
getUpdate(String id) {
|
getUpdate(String id, {bool resetVersion = false}) async {
|
||||||
appsProvider.checkUpdate(id).catchError((e) {
|
try {
|
||||||
showError(e, context);
|
setState(() {
|
||||||
return null;
|
updating = true;
|
||||||
});
|
});
|
||||||
|
await appsProvider.checkUpdate(id);
|
||||||
|
if (resetVersion) {
|
||||||
|
appsProvider.apps[id]?.app.additionalSettings['versionDetection'] =
|
||||||
|
true;
|
||||||
|
if (appsProvider.apps[id]?.app.installedVersion != null) {
|
||||||
|
appsProvider.apps[id]?.app.installedVersion =
|
||||||
|
appsProvider.apps[id]?.app.latestVersion;
|
||||||
|
}
|
||||||
|
appsProvider.saveApps([appsProvider.apps[id]!.app]);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
showError(err, context);
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
updating = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool areDownloadsRunning = appsProvider.areDownloadsRunning();
|
bool areDownloadsRunning = appsProvider.areDownloadsRunning();
|
||||||
@ -54,122 +72,113 @@ class _AppPageState extends State<AppPage> {
|
|||||||
var trackOnly = app?.app.additionalSettings['trackOnly'] == true;
|
var trackOnly = app?.app.additionalSettings['trackOnly'] == true;
|
||||||
|
|
||||||
bool isVersionDetectionStandard =
|
bool isVersionDetectionStandard =
|
||||||
app?.app.additionalSettings['versionDetection'] ==
|
app?.app.additionalSettings['versionDetection'] == true;
|
||||||
'standardVersionDetection';
|
|
||||||
|
|
||||||
bool installedVersionIsEstimate = trackOnly ||
|
bool installedVersionIsEstimate = trackOnly ||
|
||||||
(app?.app.installedVersion != null &&
|
(app?.app.installedVersion != null &&
|
||||||
app?.app.additionalSettings['versionDetection'] ==
|
app?.app.additionalSettings['versionDetection'] != true);
|
||||||
'noVersionDetection');
|
|
||||||
|
|
||||||
getInfoColumn() => Column(
|
getInfoColumn() {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
String versionLines = '';
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
bool installed = app?.app.installedVersion != null;
|
||||||
children: [
|
bool upToDate = app?.app.installedVersion == app?.app.latestVersion;
|
||||||
GestureDetector(
|
if (installed) {
|
||||||
onTap: () {
|
versionLines = '${app?.app.installedVersion} ${tr('installed')}';
|
||||||
if (app?.app.url != null) {
|
if (upToDate) {
|
||||||
launchUrlString(app?.app.url ?? '',
|
versionLines += '/${tr('latest')}';
|
||||||
mode: LaunchMode.externalApplication);
|
}
|
||||||
}
|
} else {
|
||||||
},
|
versionLines = tr('notInstalled');
|
||||||
onLongPress: () {
|
}
|
||||||
Clipboard.setData(ClipboardData(text: app?.app.url ?? ''));
|
if (!upToDate) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
versionLines += '\n${app?.app.latestVersion} ${tr('latest')}';
|
||||||
content: Text(tr('copiedToClipboard')),
|
}
|
||||||
));
|
String infoLines = tr('lastUpdateCheckX', args: [
|
||||||
},
|
app?.app.lastUpdateCheck == null
|
||||||
child: Text(
|
? tr('never')
|
||||||
app?.app.url ?? '',
|
: '${app?.app.lastUpdateCheck?.toLocal()}'
|
||||||
textAlign: TextAlign.center,
|
]);
|
||||||
style: const TextStyle(
|
if (trackOnly) {
|
||||||
decoration: TextDecoration.underline,
|
infoLines = '${tr('xIsTrackOnly', args: [tr('app')])}\n$infoLines';
|
||||||
fontStyle: FontStyle.italic,
|
}
|
||||||
fontSize: 12),
|
if (installedVersionIsEstimate) {
|
||||||
)),
|
infoLines = '${tr('pseudoVersionInUse')}\n$infoLines';
|
||||||
const SizedBox(
|
}
|
||||||
height: 32,
|
return Column(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Column(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 24),
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const SizedBox(
|
||||||
'${tr('latestVersionX', args: [
|
height: 8,
|
||||||
app?.app.latestVersion ?? tr('unknown')
|
),
|
||||||
])}\n${tr('installedVersionX', args: [
|
Text(versionLines,
|
||||||
app?.app.installedVersion ?? tr('none')
|
textAlign: TextAlign.start,
|
||||||
])}${installedVersionIsEstimate ? '\n${tr('estimateInBrackets')}' : ''}',
|
style: Theme.of(context)
|
||||||
textAlign: TextAlign.end,
|
.textTheme
|
||||||
style: Theme.of(context).textTheme.bodyLarge!,
|
.bodyLarge!
|
||||||
|
.copyWith(fontWeight: FontWeight.bold)),
|
||||||
|
app?.app.releaseDate == null
|
||||||
|
? const SizedBox.shrink()
|
||||||
|
: Text(
|
||||||
|
app!.app.releaseDate.toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (app?.app.installedVersion != null &&
|
),
|
||||||
!isVersionDetectionStandard)
|
Text(
|
||||||
Column(
|
infoLines,
|
||||||
children: [
|
textAlign: TextAlign.center,
|
||||||
const SizedBox(
|
style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12),
|
||||||
height: 16,
|
),
|
||||||
),
|
const SizedBox(
|
||||||
Text(
|
height: 48,
|
||||||
'${trackOnly ? '${tr('xIsTrackOnly', args: [
|
),
|
||||||
tr('app')
|
CategoryEditorSelector(
|
||||||
])}\n' : ''}${tr('noVersionDetection')}',
|
alignment: WrapAlignment.center,
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
preselected: app?.app.categories != null
|
||||||
|
? app!.app.categories.toSet()
|
||||||
|
: {},
|
||||||
|
onSelected: (categories) {
|
||||||
|
if (app != null) {
|
||||||
|
app.app.categories = categories;
|
||||||
|
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,
|
textAlign: TextAlign.center,
|
||||||
)
|
style: const TextStyle(fontStyle: FontStyle.italic),
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 32,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
tr('lastUpdateCheckX', args: [
|
|
||||||
app?.app.lastUpdateCheck == null
|
|
||||||
? tr('never')
|
|
||||||
: '\n${app?.app.lastUpdateCheck?.toLocal()}'
|
|
||||||
]),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 48,
|
|
||||||
),
|
|
||||||
CategoryEditorSelector(
|
|
||||||
alignment: WrapAlignment.center,
|
|
||||||
preselected: app?.app.categories != null
|
|
||||||
? app!.app.categories.toSet()
|
|
||||||
: {},
|
|
||||||
onSelected: (categories) {
|
|
||||||
if (app != null) {
|
|
||||||
app.app.categories = categories;
|
|
||||||
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),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
getFullInfoColumn() => Column(
|
getFullInfoColumn() => Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -196,29 +205,37 @@ class _AppPageState extends State<AppPage> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.displayLarge,
|
style: Theme.of(context).textTheme.displayLarge,
|
||||||
),
|
),
|
||||||
Text(
|
Text(tr('byX', args: [app?.app.author ?? tr('unknown')]),
|
||||||
tr('byX', args: [app?.app.author ?? tr('unknown')]),
|
textAlign: TextAlign.center,
|
||||||
textAlign: TextAlign.center,
|
style: Theme.of(context).textTheme.headlineMedium),
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 24,
|
||||||
),
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (app?.app.url != null) {
|
||||||
|
launchUrlString(app?.app.url ?? '',
|
||||||
|
mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLongPress: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: app?.app.url ?? ''));
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text(tr('copiedToClipboard')),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
app?.app.url ?? '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
fontStyle: FontStyle.italic),
|
||||||
|
)),
|
||||||
Text(
|
Text(
|
||||||
app?.app.id ?? '',
|
app?.app.id ?? '',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
),
|
),
|
||||||
app?.app.releaseDate == null
|
|
||||||
? const SizedBox.shrink()
|
|
||||||
: Text(
|
|
||||||
app!.app.releaseDate.toString(),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 32,
|
|
||||||
),
|
|
||||||
getInfoColumn(),
|
getInfoColumn(),
|
||||||
const SizedBox(height: 150)
|
const SizedBox(height: 150)
|
||||||
],
|
],
|
||||||
@ -287,25 +304,6 @@ class _AppPageState extends State<AppPage> {
|
|||||||
return row;
|
return row;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
items = items.map((row) {
|
|
||||||
row = row.map((e) {
|
|
||||||
if (e.key == 'versionDetection' && e is GeneratedFormDropdown) {
|
|
||||||
e.disabledOptKeys ??= [];
|
|
||||||
if (app?.app.installedVersion != null &&
|
|
||||||
app?.app.additionalSettings['versionDetection'] !=
|
|
||||||
'releaseDateAsVersion' &&
|
|
||||||
!appsProvider.isVersionDetectionPossible(app)) {
|
|
||||||
e.disabledOptKeys!.add('standardVersionDetection');
|
|
||||||
}
|
|
||||||
if (app?.app.releaseDate == null) {
|
|
||||||
e.disabledOptKeys!.add('releaseDateAsVersion');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}).toList();
|
|
||||||
return row;
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
return GeneratedFormModal(
|
return GeneratedFormModal(
|
||||||
title: tr('additionalOptions'), items: items);
|
title: tr('additionalOptions'), items: items);
|
||||||
});
|
});
|
||||||
@ -320,44 +318,41 @@ class _AppPageState extends State<AppPage> {
|
|||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
showMessage(tr('appsFromSourceAreTrackOnly'), context);
|
showMessage(tr('appsFromSourceAreTrackOnly'), context);
|
||||||
}
|
}
|
||||||
if (app.app.additionalSettings['versionDetection'] ==
|
var versionDetectionEnabled =
|
||||||
'releaseDateAsVersion') {
|
app.app.additionalSettings['versionDetection'] == true &&
|
||||||
if (originalSettings['versionDetection'] != 'releaseDateAsVersion') {
|
originalSettings['versionDetection'] != true;
|
||||||
if (app.app.releaseDate != null) {
|
var releaseDateVersionEnabled =
|
||||||
bool isUpdated =
|
app.app.additionalSettings['releaseDateAsVersion'] == true &&
|
||||||
app.app.installedVersion == app.app.latestVersion;
|
originalSettings['releaseDateAsVersion'] != true;
|
||||||
app.app.latestVersion =
|
var releaseDateVersionDisabled =
|
||||||
app.app.releaseDate!.microsecondsSinceEpoch.toString();
|
app.app.additionalSettings['releaseDateAsVersion'] != true &&
|
||||||
if (isUpdated) {
|
originalSettings['releaseDateAsVersion'] == true;
|
||||||
app.app.installedVersion = app.app.latestVersion;
|
if (releaseDateVersionEnabled) {
|
||||||
}
|
if (app.app.releaseDate != null) {
|
||||||
|
bool isUpdated = app.app.installedVersion == app.app.latestVersion;
|
||||||
|
app.app.latestVersion =
|
||||||
|
app.app.releaseDate!.microsecondsSinceEpoch.toString();
|
||||||
|
if (isUpdated) {
|
||||||
|
app.app.installedVersion = app.app.latestVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (originalSettings['versionDetection'] ==
|
} else if (releaseDateVersionDisabled) {
|
||||||
'releaseDateAsVersion') {
|
|
||||||
app.app.installedVersion =
|
app.app.installedVersion =
|
||||||
app.installedInfo?.versionName ?? app.app.installedVersion;
|
app.installedInfo?.versionName ?? app.app.installedVersion;
|
||||||
}
|
}
|
||||||
|
if (versionDetectionEnabled) {
|
||||||
|
app.app.additionalSettings['versionDetection'] = true;
|
||||||
|
app.app.additionalSettings['releaseDateAsVersion'] = false;
|
||||||
|
}
|
||||||
appsProvider.saveApps([app.app]).then((value) {
|
appsProvider.saveApps([app.app]).then((value) {
|
||||||
getUpdate(app.app.id);
|
getUpdate(app.app.id, resetVersion: versionDetectionEnabled);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getResetInstallStatusButton() => TextButton(
|
|
||||||
onPressed: app?.app == null
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
app!.app.installedVersion = null;
|
|
||||||
appsProvider.saveApps([app.app]);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
tr('resetInstallStatus'),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
));
|
|
||||||
|
|
||||||
getInstallOrUpdateButton() => TextButton(
|
getInstallOrUpdateButton() => TextButton(
|
||||||
onPressed: (app?.app.installedVersion == null ||
|
onPressed: !updating &&
|
||||||
|
(app?.app.installedVersion == null ||
|
||||||
app?.app.installedVersion != app?.app.latestVersion) &&
|
app?.app.installedVersion != app?.app.latestVersion) &&
|
||||||
!areDownloadsRunning
|
!areDownloadsRunning
|
||||||
? () async {
|
? () async {
|
||||||
@ -367,7 +362,7 @@ class _AppPageState extends State<AppPage> {
|
|||||||
app?.app.id != null ? [app!.app.id] : [],
|
app?.app.id != null ? [app!.app.id] : [],
|
||||||
globalNavigatorKey.currentContext,
|
globalNavigatorKey.currentContext,
|
||||||
);
|
);
|
||||||
if (app?.app.installedVersion != null && !trackOnly) {
|
if (res.isNotEmpty && !trackOnly) {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
showMessage(tr('appsUpdated'), context);
|
showMessage(tr('appsUpdated'), context);
|
||||||
}
|
}
|
||||||
@ -399,20 +394,10 @@ class _AppPageState extends State<AppPage> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
if (app?.app.installedVersion != null &&
|
|
||||||
app?.app.installedVersion != app?.app.latestVersion &&
|
|
||||||
!isVersionDetectionStandard &&
|
|
||||||
!trackOnly)
|
|
||||||
IconButton(
|
|
||||||
onPressed: app?.downloadProgress != null
|
|
||||||
? null
|
|
||||||
: showMarkUpdatedDialog,
|
|
||||||
tooltip: tr('markUpdated'),
|
|
||||||
icon: const Icon(Icons.done)),
|
|
||||||
if (source != null &&
|
if (source != null &&
|
||||||
source.combinedAppSpecificSettingFormItems.isNotEmpty)
|
source.combinedAppSpecificSettingFormItems.isNotEmpty)
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: app?.downloadProgress != null
|
onPressed: app?.downloadProgress != null || updating
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
var values =
|
var values =
|
||||||
@ -454,17 +439,33 @@ class _AppPageState extends State<AppPage> {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Icons.more_horiz),
|
icon: const Icon(Icons.more_horiz),
|
||||||
tooltip: tr('more')),
|
tooltip: tr('more')),
|
||||||
|
if (app?.app.installedVersion != null &&
|
||||||
|
app?.app.installedVersion != app?.app.latestVersion &&
|
||||||
|
!isVersionDetectionStandard &&
|
||||||
|
!trackOnly)
|
||||||
|
IconButton(
|
||||||
|
onPressed: app?.downloadProgress != null || updating
|
||||||
|
? null
|
||||||
|
: showMarkUpdatedDialog,
|
||||||
|
tooltip: tr('markUpdated'),
|
||||||
|
icon: const Icon(Icons.done)),
|
||||||
|
if ((!isVersionDetectionStandard || trackOnly) &&
|
||||||
|
app?.app.installedVersion != null &&
|
||||||
|
app?.app.installedVersion == app?.app.latestVersion)
|
||||||
|
IconButton(
|
||||||
|
onPressed: app?.app == null || updating
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
app!.app.installedVersion = null;
|
||||||
|
appsProvider.saveApps([app.app]);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.restore_rounded),
|
||||||
|
tooltip: tr('resetInstallStatus')),
|
||||||
const SizedBox(width: 16.0),
|
const SizedBox(width: 16.0),
|
||||||
Expanded(
|
Expanded(child: getInstallOrUpdateButton()),
|
||||||
child: (!isVersionDetectionStandard || trackOnly) &&
|
|
||||||
app?.app.installedVersion != null &&
|
|
||||||
app?.app.installedVersion ==
|
|
||||||
app?.app.latestVersion
|
|
||||||
? getResetInstallStatusButton()
|
|
||||||
: getInstallOrUpdateButton()),
|
|
||||||
const SizedBox(width: 16.0),
|
const SizedBox(width: 16.0),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: app?.downloadProgress != null
|
onPressed: app?.downloadProgress != null || updating
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
appsProvider
|
appsProvider
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -356,6 +358,16 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
String? changesUrl =
|
String? changesUrl =
|
||||||
appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url);
|
appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url);
|
||||||
String? changeLog = listedApps[appIndex].app.changeLog;
|
String? changeLog = listedApps[appIndex].app.changeLog;
|
||||||
|
if (changeLog?.split('\n').length == 1) {
|
||||||
|
if (RegExp(
|
||||||
|
'(http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?')
|
||||||
|
.hasMatch(changeLog!)) {
|
||||||
|
if (changesUrl == null) {
|
||||||
|
changesUrl = changeLog;
|
||||||
|
changeLog = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return (changeLog == null && changesUrl == null)
|
return (changeLog == null && changesUrl == null)
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
@ -419,7 +431,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getVersionText(int appIndex) {
|
getVersionText(int appIndex) {
|
||||||
return '${listedApps[appIndex].app.installedVersion ?? tr('notInstalled')}${listedApps[appIndex].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}';
|
return '${listedApps[appIndex].app.installedVersion ?? tr('notInstalled')}${listedApps[appIndex].app.additionalSettings['trackOnly'] == true ? ' ${tr('pseudoVersion')}' : ''}';
|
||||||
}
|
}
|
||||||
|
|
||||||
getChangesButtonString(int appIndex, bool hasChangeLogFn) {
|
getChangesButtonString(int appIndex, bool hasChangeLogFn) {
|
||||||
@ -694,7 +706,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
showError(e, context);
|
showError(e, context);
|
||||||
return <String>[];
|
return <String>[];
|
||||||
}).then((value) {
|
}).then((value) {
|
||||||
if (shouldInstallUpdates) {
|
if (value.isNotEmpty && shouldInstallUpdates) {
|
||||||
showMessage(tr('appsUpdated'), context);
|
showMessage(tr('appsUpdated'), context);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -871,20 +883,42 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
String urls = '';
|
String urls = '';
|
||||||
for (var a in selectedApps) {
|
for (var a in selectedApps) {
|
||||||
urls += 'obtainium://add/${a.url}\n';
|
urls += '${a.url}\n';
|
||||||
}
|
}
|
||||||
urls = urls.substring(0, urls.length - 1);
|
urls = urls.substring(0, urls.length - 1);
|
||||||
Share.share(urls,
|
Share.share(urls,
|
||||||
subject: tr('selectedAppURLsFromObtainium'));
|
subject: 'Obtainium - ${tr('appsString')}');
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
tooltip: tr('shareSelectedAppURLs'),
|
tooltip: tr('shareSelectedAppURLs'),
|
||||||
icon: const Icon(Icons.share),
|
icon: const Icon(Icons.share_rounded),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: resetSelectedAppsInstallStatuses,
|
onPressed: selectedAppIds.isEmpty
|
||||||
tooltip: tr('resetInstallStatus'),
|
? null
|
||||||
icon: const Icon(Icons.restore_page_outlined),
|
: () {
|
||||||
|
String urls =
|
||||||
|
'<p>${tr('customLinkMessage')}:</p>\n\n<ul>\n';
|
||||||
|
for (var a in selectedApps) {
|
||||||
|
urls +=
|
||||||
|
' <li><a href="obtainium://app/${Uri.encodeComponent(jsonEncode({
|
||||||
|
'id': a.id,
|
||||||
|
'url': a.url,
|
||||||
|
'author': a.author,
|
||||||
|
'name': a.name,
|
||||||
|
'preferredApkIndex':
|
||||||
|
a.preferredApkIndex,
|
||||||
|
'additionalSettings':
|
||||||
|
jsonEncode(a.additionalSettings)
|
||||||
|
}))}">${a.name}</a></li>\n';
|
||||||
|
}
|
||||||
|
urls +=
|
||||||
|
'</ul>\n\n<p><a href="$obtainiumUrl">${tr('about')}</a></p>';
|
||||||
|
Share.share(urls,
|
||||||
|
subject: 'Obtainium - ${tr('appsString')}');
|
||||||
|
},
|
||||||
|
tooltip: tr('shareAppConfigLinks'),
|
||||||
|
icon: const Icon(Icons.ios_share),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
@ -1004,7 +1038,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
style: const ButtonStyle(visualDensity: VisualDensity.compact),
|
style: const ButtonStyle(visualDensity: VisualDensity.compact),
|
||||||
tooltip: isFilterOff ? tr('filter') : tr('filterActive'),
|
tooltip: '${tr('filter')}${isFilterOff ? '' : ' *'}',
|
||||||
onPressed: isFilterOff
|
onPressed: isFilterOff
|
||||||
? showFilterDialog
|
? showFilterDialog
|
||||||
: () {
|
: () {
|
||||||
|
@ -199,10 +199,11 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
...source.searchQuerySettingFormItems.map((e) => [e]),
|
...source.searchQuerySettingFormItems.map((e) => [e]),
|
||||||
[
|
[
|
||||||
GeneratedFormTextField('url',
|
GeneratedFormTextField('url',
|
||||||
label: source.host != null
|
label: source.hosts.isNotEmpty
|
||||||
? tr('overrideSource')
|
? tr('overrideSource')
|
||||||
: plural('url', 1).substring(2),
|
: plural('url', 1).substring(2),
|
||||||
defaultValue: source.host ?? '',
|
defaultValue:
|
||||||
|
source.hosts.isNotEmpty ? source.hosts[0] : '',
|
||||||
required: true)
|
required: true)
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -212,7 +213,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
importInProgress = true;
|
importInProgress = true;
|
||||||
});
|
});
|
||||||
if (values['url'] != source.host) {
|
if (source.hosts.isEmpty || values['url'] != source.hosts[0]) {
|
||||||
source = sourceProvider.getSource(values['url'],
|
source = sourceProvider.getSource(values['url'],
|
||||||
overrideSource: source.runtimeType.toString());
|
overrideSource: source.runtimeType.toString());
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,9 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
value: InstallMethodSettings.normal,
|
value: InstallMethodSettings.normal,
|
||||||
child: Text(tr('normal')),
|
child: Text(tr('normal')),
|
||||||
),
|
),
|
||||||
DropdownMenuItem(
|
const DropdownMenuItem(
|
||||||
value: InstallMethodSettings.shizuku,
|
value: InstallMethodSettings.shizuku,
|
||||||
child: Text(tr('shizuku')),
|
child: Text('Shizuku'),
|
||||||
),
|
),
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
value: InstallMethodSettings.root,
|
value: InstallMethodSettings.root,
|
||||||
@ -79,14 +79,14 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
var colourDropdown = DropdownButtonFormField(
|
var colourDropdown = DropdownButtonFormField(
|
||||||
decoration: InputDecoration(labelText: tr('colour')),
|
decoration: InputDecoration(labelText: tr('colour')),
|
||||||
value: settingsProvider.colour,
|
value: settingsProvider.colour,
|
||||||
items: [
|
items: const [
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
value: ColourSettings.basic,
|
value: ColourSettings.basic,
|
||||||
child: Text(tr('obtainium')),
|
child: Text('Obtainium'),
|
||||||
),
|
),
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
value: ColourSettings.materialYou,
|
value: ColourSettings.materialYou,
|
||||||
child: Text(tr('materialYou')),
|
child: Text('Material You'),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -416,13 +416,17 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
value: settingsProvider.useSystemFont,
|
value: settingsProvider.useSystemFont,
|
||||||
onChanged: (useSystemFont) {
|
onChanged: (useSystemFont) {
|
||||||
if (useSystemFont) {
|
if (useSystemFont) {
|
||||||
NativeFeatures.loadSystemFont().then((fontLoadRes) {
|
NativeFeatures.loadSystemFont()
|
||||||
|
.then((fontLoadRes) {
|
||||||
if (fontLoadRes == 'ok') {
|
if (fontLoadRes == 'ok') {
|
||||||
settingsProvider.useSystemFont = true;
|
settingsProvider.useSystemFont =
|
||||||
|
true;
|
||||||
} else {
|
} else {
|
||||||
showError(ObtainiumError(
|
showError(
|
||||||
tr('systemFontError', args: [fontLoadRes])
|
ObtainiumError(tr(
|
||||||
), context);
|
'systemFontError',
|
||||||
|
args: [fontLoadRes])),
|
||||||
|
context);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -628,38 +632,9 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
label: Text(tr('appLogs'))),
|
label: Text(tr('appLogs'))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Divider(
|
const SizedBox(
|
||||||
height: 32,
|
height: 16,
|
||||||
),
|
)
|
||||||
// Padding(
|
|
||||||
// padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
|
||||||
// child: Column(children: [
|
|
||||||
// Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
// children: [
|
|
||||||
// Flexible(child: Text(tr('debugMenu'))),
|
|
||||||
// Switch(
|
|
||||||
// value: settingsProvider.showDebugOpts,
|
|
||||||
// onChanged: (value) {
|
|
||||||
// settingsProvider.showDebugOpts = value;
|
|
||||||
// })
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// if (settingsProvider.showDebugOpts)
|
|
||||||
// Column(
|
|
||||||
// crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
// children: [
|
|
||||||
// height16,
|
|
||||||
// TextButton(
|
|
||||||
// onPressed: () {
|
|
||||||
// bgUpdateCheck('taskId', null);
|
|
||||||
// showMessage(tr('bgTaskStarted'), context);
|
|
||||||
// },
|
|
||||||
// child: Text(tr('runBgCheckNow')))
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ]),
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -167,8 +167,24 @@ String hashListOfLists(List<List<int>> data) {
|
|||||||
return hash.hashCode.toString();
|
return hash.hashCode.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> checkDownloadHash(String url,
|
Future<String> checkPartialDownloadHashDynamic(String url,
|
||||||
{int bytesToGrab = 1024, Map<String, String>? headers}) async {
|
{int startingSize = 1024,
|
||||||
|
int lowerLimit = 128,
|
||||||
|
Map<String, String>? headers}) async {
|
||||||
|
for (int i = startingSize; i >= lowerLimit; i -= 256) {
|
||||||
|
List<String> ab = await Future.wait([
|
||||||
|
checkPartialDownloadHash(url, i, headers: headers),
|
||||||
|
checkPartialDownloadHash(url, i, headers: headers)
|
||||||
|
]);
|
||||||
|
if (ab[0] == ab[1]) {
|
||||||
|
return ab[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw NoVersionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> checkPartialDownloadHash(String url, int bytesToGrab,
|
||||||
|
{Map<String, String>? headers}) async {
|
||||||
var req = Request('GET', Uri.parse(url));
|
var req = Request('GET', Uri.parse(url));
|
||||||
if (headers != null) {
|
if (headers != null) {
|
||||||
req.headers.addAll(headers);
|
req.headers.addAll(headers);
|
||||||
@ -227,13 +243,29 @@ Future<File> downloadFile(
|
|||||||
tempDownloadedFile.deleteSync(recursive: true);
|
tempDownloadedFile.deleteSync(recursive: true);
|
||||||
throw response.reasonPhrase ?? tr('unexpectedError');
|
throw response.reasonPhrase ?? tr('unexpectedError');
|
||||||
}
|
}
|
||||||
tempDownloadedFile.renameSync(downloadedFile.path);
|
if (tempDownloadedFile.existsSync()) {
|
||||||
|
tempDownloadedFile.renameSync(downloadedFile.path);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
client.close();
|
client.close();
|
||||||
}
|
}
|
||||||
return downloadedFile;
|
return downloadedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<PackageInfo?> getInstalledInfo(String? packageName,
|
||||||
|
{bool printErr = true}) async {
|
||||||
|
if (packageName != null) {
|
||||||
|
try {
|
||||||
|
return await pm.getPackageInfo(packageName: packageName);
|
||||||
|
} catch (e) {
|
||||||
|
if (printErr) {
|
||||||
|
print(e); // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
class AppsProvider with ChangeNotifier {
|
class AppsProvider with ChangeNotifier {
|
||||||
// In memory App state (should always be kept in sync with local storage versions)
|
// In memory App state (should always be kept in sync with local storage versions)
|
||||||
Map<String, AppInMemory> apps = {};
|
Map<String, AppInMemory> apps = {};
|
||||||
@ -326,13 +358,15 @@ class AppsProvider with ChangeNotifier {
|
|||||||
AppSource source = SourceProvider()
|
AppSource source = SourceProvider()
|
||||||
.getSource(app.url, overrideSource: app.overrideSource);
|
.getSource(app.url, overrideSource: app.overrideSource);
|
||||||
String downloadUrl = await source.apkUrlPrefetchModifier(
|
String downloadUrl = await source.apkUrlPrefetchModifier(
|
||||||
app.apkUrls[app.preferredApkIndex].value, app.url);
|
app.apkUrls[app.preferredApkIndex].value,
|
||||||
|
app.url,
|
||||||
|
app.additionalSettings);
|
||||||
var notif = DownloadNotification(app.finalName, 100);
|
var notif = DownloadNotification(app.finalName, 100);
|
||||||
notificationsProvider?.cancel(notif.id);
|
notificationsProvider?.cancel(notif.id);
|
||||||
int? prevProg;
|
int? prevProg;
|
||||||
var fileNameNoExt = '${app.id}-${downloadUrl.hashCode}';
|
var fileNameNoExt = '${app.id}-${downloadUrl.hashCode}';
|
||||||
var headers = await source.getRequestHeaders(
|
var headers = await source.getRequestHeaders(app.additionalSettings,
|
||||||
additionalSettings: app.additionalSettings, forAPKDownload: true);
|
forAPKDownload: true);
|
||||||
var downloadedFile = await downloadFileWithRetry(
|
var downloadedFile = await downloadFileWithRetry(
|
||||||
downloadUrl, fileNameNoExt,
|
downloadUrl, fileNameNoExt,
|
||||||
headers: headers, (double? progress) {
|
headers: headers, (double? progress) {
|
||||||
@ -498,9 +532,18 @@ class AppsProvider with ChangeNotifier {
|
|||||||
{bool needsBGWorkaround = false}) async {
|
{bool needsBGWorkaround = false}) async {
|
||||||
var newInfo =
|
var newInfo =
|
||||||
await pm.getPackageArchiveInfo(archiveFilePath: file.file.path);
|
await pm.getPackageArchiveInfo(archiveFilePath: file.file.path);
|
||||||
|
if (newInfo == null) {
|
||||||
|
try {
|
||||||
|
file.file.deleteSync(recursive: true);
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
} finally {
|
||||||
|
throw ObtainiumError(tr('badDownload'));
|
||||||
|
}
|
||||||
|
}
|
||||||
PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id);
|
PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id);
|
||||||
if (appInfo != null &&
|
if (appInfo != null &&
|
||||||
newInfo!.versionCode! < appInfo.versionCode! &&
|
newInfo.versionCode! < appInfo.versionCode! &&
|
||||||
!(await canDowngradeApps())) {
|
!(await canDowngradeApps())) {
|
||||||
throw DowngradeError();
|
throw DowngradeError();
|
||||||
}
|
}
|
||||||
@ -637,6 +680,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
MapEntry<String, String>? apkUrl;
|
MapEntry<String, String>? apkUrl;
|
||||||
var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true;
|
var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true;
|
||||||
if (!trackOnly) {
|
if (!trackOnly) {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
apkUrl = await confirmApkUrl(apps[id]!.app, context);
|
apkUrl = await confirmApkUrl(apps[id]!.app, context);
|
||||||
}
|
}
|
||||||
if (apkUrl != null) {
|
if (apkUrl != null) {
|
||||||
@ -773,20 +817,6 @@ class AppsProvider with ChangeNotifier {
|
|||||||
return appsDir;
|
return appsDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<PackageInfo?> getInstalledInfo(String? packageName,
|
|
||||||
{bool printErr = true}) async {
|
|
||||||
if (packageName != null) {
|
|
||||||
try {
|
|
||||||
return await pm.getPackageInfo(packageName: packageName);
|
|
||||||
} catch (e) {
|
|
||||||
if (printErr) {
|
|
||||||
print(e); // OK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isVersionDetectionPossible(AppInMemory? app) {
|
bool isVersionDetectionPossible(AppInMemory? app) {
|
||||||
if (app?.app == null) {
|
if (app?.app == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -796,13 +826,16 @@ class AppsProvider with ChangeNotifier {
|
|||||||
SourceProvider()
|
SourceProvider()
|
||||||
.getSource(app.app.url, overrideSource: app.app.overrideSource)
|
.getSource(app.app.url, overrideSource: app.app.overrideSource)
|
||||||
.naiveStandardVersionDetection;
|
.naiveStandardVersionDetection;
|
||||||
|
String? realInstalledVersion =
|
||||||
|
app.app.additionalSettings['useVersionCodeAsOSVersion'] == true
|
||||||
|
? app.installedInfo?.versionCode.toString()
|
||||||
|
: app.installedInfo?.versionName;
|
||||||
return app.app.additionalSettings['trackOnly'] != true &&
|
return app.app.additionalSettings['trackOnly'] != true &&
|
||||||
app.app.additionalSettings['versionDetection'] !=
|
app.app.additionalSettings['releaseDateAsVersion'] != true &&
|
||||||
'releaseDateAsVersion' &&
|
realInstalledVersion != null &&
|
||||||
app.installedInfo?.versionName != null &&
|
|
||||||
app.app.installedVersion != null &&
|
app.app.installedVersion != null &&
|
||||||
(reconcileVersionDifferences(app.installedInfo!.versionName!,
|
(reconcileVersionDifferences(
|
||||||
app.app.installedVersion!) !=
|
realInstalledVersion, app.app.installedVersion!) !=
|
||||||
null ||
|
null ||
|
||||||
naiveStandardVersionDetection);
|
naiveStandardVersionDetection);
|
||||||
}
|
}
|
||||||
@ -814,37 +847,39 @@ class AppsProvider with ChangeNotifier {
|
|||||||
var modded = false;
|
var modded = false;
|
||||||
var trackOnly = app.additionalSettings['trackOnly'] == true;
|
var trackOnly = app.additionalSettings['trackOnly'] == true;
|
||||||
var versionDetectionIsStandard =
|
var versionDetectionIsStandard =
|
||||||
app.additionalSettings['versionDetection'] ==
|
app.additionalSettings['versionDetection'] == true;
|
||||||
'standardVersionDetection';
|
|
||||||
var naiveStandardVersionDetection =
|
var naiveStandardVersionDetection =
|
||||||
app.additionalSettings['naiveStandardVersionDetection'] == true ||
|
app.additionalSettings['naiveStandardVersionDetection'] == true ||
|
||||||
SourceProvider()
|
SourceProvider()
|
||||||
.getSource(app.url, overrideSource: app.overrideSource)
|
.getSource(app.url, overrideSource: app.overrideSource)
|
||||||
.naiveStandardVersionDetection;
|
.naiveStandardVersionDetection;
|
||||||
|
String? realInstalledVersion =
|
||||||
|
app.additionalSettings['useVersionCodeAsOSVersion'] == true
|
||||||
|
? installedInfo?.versionCode.toString()
|
||||||
|
: installedInfo?.versionName;
|
||||||
// FIRST, COMPARE THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE ONE IS NULL
|
// FIRST, COMPARE THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE ONE IS NULL
|
||||||
if (installedInfo == null && app.installedVersion != null && !trackOnly) {
|
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
|
// App says it's installed but isn't really (and isn't track only) - set to not installed
|
||||||
app.installedVersion = null;
|
app.installedVersion = null;
|
||||||
modded = true;
|
modded = true;
|
||||||
} else if (installedInfo?.versionName != null &&
|
} else if (realInstalledVersion != null && app.installedVersion == null) {
|
||||||
app.installedVersion == null) {
|
// App says it's not installed but really is - set to installed and use real package versionName (or versionCode if chosen)
|
||||||
// App says it's not installed but really is - set to installed and use real package versionName
|
app.installedVersion = realInstalledVersion;
|
||||||
app.installedVersion = installedInfo!.versionName;
|
|
||||||
modded = true;
|
modded = true;
|
||||||
}
|
}
|
||||||
// SECOND, RECONCILE DIFFERENCES BETWEEN THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE NEITHER IS NULL
|
// SECOND, RECONCILE DIFFERENCES BETWEEN THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE NEITHER IS NULL
|
||||||
if (installedInfo?.versionName != null &&
|
if (realInstalledVersion != null &&
|
||||||
installedInfo!.versionName != app.installedVersion &&
|
realInstalledVersion != app.installedVersion &&
|
||||||
versionDetectionIsStandard) {
|
versionDetectionIsStandard) {
|
||||||
// App's reported version and real version don't match (and it uses standard version detection)
|
// App's reported version and real version don't match (and it uses standard version detection)
|
||||||
// If they share a standard format (and are still different under it), update the reported version accordingly
|
// If they share a standard format (and are still different under it), update the reported version accordingly
|
||||||
var correctedInstalledVersion = reconcileVersionDifferences(
|
var correctedInstalledVersion = reconcileVersionDifferences(
|
||||||
installedInfo.versionName!, app.installedVersion!);
|
realInstalledVersion, app.installedVersion!);
|
||||||
if (correctedInstalledVersion?.key == false) {
|
if (correctedInstalledVersion?.key == false) {
|
||||||
app.installedVersion = correctedInstalledVersion!.value;
|
app.installedVersion = correctedInstalledVersion!.value;
|
||||||
modded = true;
|
modded = true;
|
||||||
} else if (naiveStandardVersionDetection) {
|
} else if (naiveStandardVersionDetection) {
|
||||||
app.installedVersion = installedInfo.versionName;
|
app.installedVersion = realInstalledVersion;
|
||||||
modded = true;
|
modded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -866,7 +901,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
versionDetectionIsStandard &&
|
versionDetectionIsStandard &&
|
||||||
!isVersionDetectionPossible(
|
!isVersionDetectionPossible(
|
||||||
AppInMemory(app, null, installedInfo, null))) {
|
AppInMemory(app, null, installedInfo, null))) {
|
||||||
app.additionalSettings['versionDetection'] = 'noVersionDetection';
|
app.additionalSettings['versionDetection'] = false;
|
||||||
logs.add('Could not reconcile version formats for: ${app.id}');
|
logs.add('Could not reconcile version formats for: ${app.id}');
|
||||||
modded = true;
|
modded = true;
|
||||||
}
|
}
|
||||||
@ -908,6 +943,17 @@ class AppsProvider with ChangeNotifier {
|
|||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> updateInstallStatusInMemory(AppInMemory app) async {
|
||||||
|
apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id);
|
||||||
|
apps[app.app.id]?.icon =
|
||||||
|
await apps[app.app.id]?.installedInfo?.applicationInfo?.getAppIcon();
|
||||||
|
apps[app.app.id]?.app.name = await (apps[app.app.id]
|
||||||
|
?.installedInfo
|
||||||
|
?.applicationInfo
|
||||||
|
?.getAppLabel()) ??
|
||||||
|
app.name;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> loadApps({String? singleId}) async {
|
Future<void> loadApps({String? singleId}) async {
|
||||||
while (loadingApps) {
|
while (loadingApps) {
|
||||||
await Future.delayed(const Duration(microseconds: 1));
|
await Future.delayed(const Duration(microseconds: 1));
|
||||||
@ -956,19 +1002,11 @@ class AppsProvider with ChangeNotifier {
|
|||||||
NotificationsProvider().notify(
|
NotificationsProvider().notify(
|
||||||
AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
|
AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
|
||||||
}
|
}
|
||||||
|
// Get install status and other OS info for each App (slow)
|
||||||
for (var app in apps.values) {
|
await Future.wait(apps.values.map((app) {
|
||||||
// Get install status and other OS info for each App (slow)
|
return updateInstallStatusInMemory(app);
|
||||||
apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id);
|
}));
|
||||||
apps[app.app.id]?.icon =
|
notifyListeners();
|
||||||
await apps[app.app.id]?.installedInfo?.applicationInfo?.getAppIcon();
|
|
||||||
apps[app.app.id]?.app.name = await (apps[app.app.id]
|
|
||||||
?.installedInfo
|
|
||||||
?.applicationInfo
|
|
||||||
?.getAppLabel()) ??
|
|
||||||
app.name;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
// Reconcile version differences
|
// Reconcile version differences
|
||||||
List<App> modifiedApps = [];
|
List<App> modifiedApps = [];
|
||||||
for (var app in apps.values) {
|
for (var app in apps.values) {
|
||||||
@ -991,7 +1029,6 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingApps = false;
|
loadingApps = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@ -1289,8 +1326,11 @@ class AppsProvider with ChangeNotifier {
|
|||||||
await Future.delayed(const Duration(microseconds: 1));
|
await Future.delayed(const Duration(microseconds: 1));
|
||||||
}
|
}
|
||||||
for (App a in importedApps) {
|
for (App a in importedApps) {
|
||||||
|
var installedInfo = await getInstalledInfo(a.id, printErr: false);
|
||||||
a.installedVersion =
|
a.installedVersion =
|
||||||
(await getInstalledInfo(a.id, printErr: false))?.versionName;
|
a.additionalSettings['useVersionCodeAsOSVersion'] == true
|
||||||
|
? installedInfo?.versionCode.toString()
|
||||||
|
: installedInfo?.versionName;
|
||||||
}
|
}
|
||||||
await saveApps(importedApps, onlyIfExists: false);
|
await saveApps(importedApps, onlyIfExists: false);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -14,8 +14,9 @@ import 'package:permission_handler/permission_handler.dart';
|
|||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:shared_storage/shared_storage.dart' as saf;
|
import 'package:shared_storage/shared_storage.dart' as saf;
|
||||||
|
|
||||||
String obtainiumTempId = 'imranr98_obtainium_${GitHub().host}';
|
String obtainiumTempId = 'imranr98_obtainium_${GitHub().hosts[0]}';
|
||||||
String obtainiumId = 'dev.imranr.obtainium';
|
String obtainiumId = 'dev.imranr.obtainium';
|
||||||
|
String obtainiumUrl = 'https://github.com/ImranR98/Obtainium';
|
||||||
|
|
||||||
enum InstallMethodSettings { normal, shizuku, root }
|
enum InstallMethodSettings { normal, shizuku, root }
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import 'package:obtainium/app_sources/apkmirror.dart';
|
|||||||
import 'package:obtainium/app_sources/apkpure.dart';
|
import 'package:obtainium/app_sources/apkpure.dart';
|
||||||
import 'package:obtainium/app_sources/aptoide.dart';
|
import 'package:obtainium/app_sources/aptoide.dart';
|
||||||
import 'package:obtainium/app_sources/codeberg.dart';
|
import 'package:obtainium/app_sources/codeberg.dart';
|
||||||
|
import 'package:obtainium/app_sources/directAPKLink.dart';
|
||||||
import 'package:obtainium/app_sources/fdroid.dart';
|
import 'package:obtainium/app_sources/fdroid.dart';
|
||||||
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
||||||
import 'package:obtainium/app_sources/github.dart';
|
import 'package:obtainium/app_sources/github.dart';
|
||||||
@ -19,7 +20,6 @@ import 'package:obtainium/app_sources/huaweiappgallery.dart';
|
|||||||
import 'package:obtainium/app_sources/izzyondroid.dart';
|
import 'package:obtainium/app_sources/izzyondroid.dart';
|
||||||
import 'package:obtainium/app_sources/html.dart';
|
import 'package:obtainium/app_sources/html.dart';
|
||||||
import 'package:obtainium/app_sources/jenkins.dart';
|
import 'package:obtainium/app_sources/jenkins.dart';
|
||||||
import 'package:obtainium/app_sources/mullvad.dart';
|
|
||||||
import 'package:obtainium/app_sources/neutroncode.dart';
|
import 'package:obtainium/app_sources/neutroncode.dart';
|
||||||
import 'package:obtainium/app_sources/signal.dart';
|
import 'package:obtainium/app_sources/signal.dart';
|
||||||
import 'package:obtainium/app_sources/sourceforge.dart';
|
import 'package:obtainium/app_sources/sourceforge.dart';
|
||||||
@ -104,6 +104,21 @@ appJSONCompatibilityModifiers(Map<String, dynamic> json) {
|
|||||||
additionalSettings.remove('releaseDateAsVersion');
|
additionalSettings.remove('releaseDateAsVersion');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Convert dropdown style version detection options back into bool style
|
||||||
|
if (additionalSettings['versionDetection'] == 'standardVersionDetection') {
|
||||||
|
additionalSettings['versionDetection'] = true;
|
||||||
|
} else if (additionalSettings['versionDetection'] == 'noVersionDetection') {
|
||||||
|
additionalSettings['versionDetection'] = false;
|
||||||
|
} else if (additionalSettings['versionDetection'] == 'releaseDateAsVersion') {
|
||||||
|
additionalSettings['versionDetection'] = false;
|
||||||
|
additionalSettings['releaseDateAsVersion'] = true;
|
||||||
|
}
|
||||||
|
// Convert bool style pseudo version method to dropdown style
|
||||||
|
if (originalAdditionalSettings['supportFixedAPKURL'] == true) {
|
||||||
|
additionalSettings['defaultPseudoVersioningMethod'] = 'partialAPKHash';
|
||||||
|
} else if (originalAdditionalSettings['supportFixedAPKURL'] == false) {
|
||||||
|
additionalSettings['defaultPseudoVersioningMethod'] = 'APKLinkHash';
|
||||||
|
}
|
||||||
// Ensure additionalSettings are correctly typed
|
// Ensure additionalSettings are correctly typed
|
||||||
for (var item in formItems) {
|
for (var item in formItems) {
|
||||||
if (additionalSettings[item.key] != null) {
|
if (additionalSettings[item.key] != null) {
|
||||||
@ -277,9 +292,10 @@ class App {
|
|||||||
json['installedVersion'] == null
|
json['installedVersion'] == null
|
||||||
? null
|
? null
|
||||||
: json['installedVersion'] as String,
|
: json['installedVersion'] as String,
|
||||||
json['latestVersion'] as String,
|
(json['latestVersion'] ?? tr('unknown')) as String,
|
||||||
assumed2DlistToStringMapList(jsonDecode(json['apkUrls'])),
|
assumed2DlistToStringMapList(jsonDecode(
|
||||||
json['preferredApkIndex'] as int,
|
(json['apkUrls'] ?? '[["placeholder", "placeholder"]]'))),
|
||||||
|
(json['preferredApkIndex'] ?? -1) as int,
|
||||||
jsonDecode(json['additionalSettings']) as Map<String, dynamic>,
|
jsonDecode(json['additionalSettings']) as Map<String, dynamic>,
|
||||||
json['lastUpdateCheck'] == null
|
json['lastUpdateCheck'] == null
|
||||||
? null
|
? null
|
||||||
@ -366,8 +382,12 @@ List<MapEntry<String, String>> getApkUrlsFromUrls(List<String> urls) =>
|
|||||||
return MapEntry(apkSegs.isNotEmpty ? apkSegs.last : segments.last, e);
|
return MapEntry(apkSegs.isNotEmpty ? apkSegs.last : segments.last, e);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
|
getSourceRegex(List<String> hosts) {
|
||||||
|
return '(${hosts.join('|').replaceAll('.', '\\.')})';
|
||||||
|
}
|
||||||
|
|
||||||
abstract class AppSource {
|
abstract class AppSource {
|
||||||
String? host;
|
List<String> hosts = [];
|
||||||
bool hostChanged = false;
|
bool hostChanged = false;
|
||||||
late String name;
|
late String name;
|
||||||
bool enforceTrackOnly = false;
|
bool enforceTrackOnly = false;
|
||||||
@ -376,28 +396,24 @@ abstract class AppSource {
|
|||||||
bool allowSubDomains = false;
|
bool allowSubDomains = false;
|
||||||
bool naiveStandardVersionDetection = false;
|
bool naiveStandardVersionDetection = false;
|
||||||
bool neverAutoSelect = false;
|
bool neverAutoSelect = false;
|
||||||
|
bool showReleaseDateAsVersionToggle = false;
|
||||||
|
bool versionDetectionDisallowed = false;
|
||||||
|
List<String> excludeCommonSettingKeys = [];
|
||||||
|
|
||||||
AppSource() {
|
AppSource() {
|
||||||
name = runtimeType.toString();
|
name = runtimeType.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
overrideVersionDetectionFormDefault(String vd,
|
overrideAdditionalAppSpecificSourceAgnosticSettingSwitch(String key,
|
||||||
{bool disableStandard = false, bool disableRelDate = false}) {
|
{bool disabled = true, bool defaultValue = true}) {
|
||||||
additionalAppSpecificSourceAgnosticSettingFormItems =
|
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly =
|
||||||
additionalAppSpecificSourceAgnosticSettingFormItems.map((e) {
|
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly
|
||||||
|
.map((e) {
|
||||||
return e.map((e2) {
|
return e.map((e2) {
|
||||||
if (e2.key == 'versionDetection') {
|
if (e2.key == key) {
|
||||||
var item = e2 as GeneratedFormDropdown;
|
var item = e2 as GeneratedFormSwitch;
|
||||||
item.defaultValue = vd;
|
item.disabled = disabled;
|
||||||
item.disabledOptKeys = [];
|
item.defaultValue = defaultValue;
|
||||||
if (disableStandard) {
|
|
||||||
item.disabledOptKeys?.add('standardVersionDetection');
|
|
||||||
}
|
|
||||||
if (disableRelDate) {
|
|
||||||
item.disabledOptKeys?.add('releaseDateAsVersion');
|
|
||||||
}
|
|
||||||
item.disabledOptKeys =
|
|
||||||
item.disabledOptKeys?.where((element) => element != vd).toList();
|
|
||||||
}
|
}
|
||||||
return e2;
|
return e2;
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -413,8 +429,8 @@ abstract class AppSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, String>?> getRequestHeaders(
|
Future<Map<String, String>?> getRequestHeaders(
|
||||||
{Map<String, dynamic> additionalSettings = const <String, dynamic>{},
|
Map<String, dynamic> additionalSettings,
|
||||||
bool forAPKDownload = false}) async {
|
{bool forAPKDownload = false}) async {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,12 +438,10 @@ abstract class AppSource {
|
|||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Response> sourceRequest(String url,
|
Future<Response> sourceRequest(
|
||||||
{bool followRedirects = true,
|
String url, Map<String, dynamic> additionalSettings,
|
||||||
Map<String, dynamic> additionalSettings =
|
{bool followRedirects = true}) async {
|
||||||
const <String, dynamic>{}}) async {
|
var requestHeaders = await getRequestHeaders(additionalSettings);
|
||||||
var requestHeaders =
|
|
||||||
await getRequestHeaders(additionalSettings: additionalSettings);
|
|
||||||
if (requestHeaders != null || followRedirects == false) {
|
if (requestHeaders != null || followRedirects == false) {
|
||||||
var req = Request('GET', Uri.parse(url));
|
var req = Request('GET', Uri.parse(url));
|
||||||
req.followRedirects = followRedirects;
|
req.followRedirects = followRedirects;
|
||||||
@ -455,7 +469,7 @@ abstract class AppSource {
|
|||||||
|
|
||||||
// Some additional data may be needed for Apps regardless of Source
|
// Some additional data may be needed for Apps regardless of Source
|
||||||
List<List<GeneratedFormItem>>
|
List<List<GeneratedFormItem>>
|
||||||
additionalAppSpecificSourceAgnosticSettingFormItems = [
|
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly = [
|
||||||
[
|
[
|
||||||
GeneratedFormSwitch(
|
GeneratedFormSwitch(
|
||||||
'trackOnly',
|
'trackOnly',
|
||||||
@ -473,16 +487,12 @@ abstract class AppSource {
|
|||||||
label: tr('matchGroupToUse'), required: false, hint: '\$0')
|
label: tr('matchGroupToUse'), required: false, hint: '\$0')
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
GeneratedFormDropdown(
|
GeneratedFormSwitch('versionDetection',
|
||||||
'versionDetection',
|
label: tr('versionDetectionExplanation'), defaultValue: true)
|
||||||
[
|
],
|
||||||
MapEntry(
|
[
|
||||||
'standardVersionDetection', tr('standardVersionDetection')),
|
GeneratedFormSwitch('useVersionCodeAsOSVersion',
|
||||||
MapEntry('releaseDateAsVersion', tr('releaseDateAsVersion')),
|
label: tr('useVersionCodeAsOSVersion'), defaultValue: false)
|
||||||
MapEntry('noVersionDetection', tr('noVersionDetection'))
|
|
||||||
],
|
|
||||||
label: tr('versionDetection'),
|
|
||||||
defaultValue: 'standardVersionDetection')
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
GeneratedFormTextField('apkFilterRegEx',
|
GeneratedFormTextField('apkFilterRegEx',
|
||||||
@ -494,6 +504,11 @@ abstract class AppSource {
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
GeneratedFormSwitch('invertAPKFilter',
|
||||||
|
label: '${tr('invertRegEx')} (${tr('filterAPKsByRegEx')})',
|
||||||
|
defaultValue: false)
|
||||||
|
],
|
||||||
[
|
[
|
||||||
GeneratedFormSwitch('autoApkFilterByArch',
|
GeneratedFormSwitch('autoApkFilterByArch',
|
||||||
label: tr('autoApkFilterByArch'), defaultValue: true)
|
label: tr('autoApkFilterByArch'), defaultValue: true)
|
||||||
@ -512,9 +527,48 @@ abstract class AppSource {
|
|||||||
|
|
||||||
// Previous 2 variables combined into one at runtime for convenient usage
|
// Previous 2 variables combined into one at runtime for convenient usage
|
||||||
List<List<GeneratedFormItem>> get combinedAppSpecificSettingFormItems {
|
List<List<GeneratedFormItem>> get combinedAppSpecificSettingFormItems {
|
||||||
|
if (showReleaseDateAsVersionToggle == true) {
|
||||||
|
if (additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly
|
||||||
|
.indexWhere((List<GeneratedFormItem> e) =>
|
||||||
|
e.indexWhere((GeneratedFormItem i) =>
|
||||||
|
i.key == 'releaseDateAsVersion') >=
|
||||||
|
0) <
|
||||||
|
0) {
|
||||||
|
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly.insert(
|
||||||
|
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly
|
||||||
|
.indexWhere((List<GeneratedFormItem> e) =>
|
||||||
|
e.indexWhere((GeneratedFormItem i) =>
|
||||||
|
i.key == 'versionDetection') >=
|
||||||
|
0) +
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
GeneratedFormSwitch('releaseDateAsVersion',
|
||||||
|
label:
|
||||||
|
'${tr('releaseDateAsVersion')} (${tr('pseudoVersion')})',
|
||||||
|
defaultValue: false)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly =
|
||||||
|
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly
|
||||||
|
.map((e) => e
|
||||||
|
.where((ee) => !excludeCommonSettingKeys.contains(ee.key))
|
||||||
|
.toList())
|
||||||
|
.where((e) => e.isNotEmpty)
|
||||||
|
.toList();
|
||||||
|
if (versionDetectionDisallowed) {
|
||||||
|
overrideAdditionalAppSpecificSourceAgnosticSettingSwitch(
|
||||||
|
'versionDetection',
|
||||||
|
disabled: true,
|
||||||
|
defaultValue: false);
|
||||||
|
overrideAdditionalAppSpecificSourceAgnosticSettingSwitch(
|
||||||
|
'useVersionCodeAsOSVersion',
|
||||||
|
disabled: true,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
...additionalSourceAppSpecificSettingFormItems,
|
...additionalSourceAppSpecificSettingFormItems,
|
||||||
...additionalAppSpecificSourceAgnosticSettingFormItems
|
...additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,8 +598,8 @@ abstract class AppSource {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> apkUrlPrefetchModifier(
|
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
|
||||||
String apkUrl, String standardUrl) async {
|
Map<String, dynamic> additionalSettings) async {
|
||||||
return apkUrl;
|
return apkUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,6 +713,20 @@ String? extractVersion(String? versionExtractionRegEx, String? matchGroupString,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<MapEntry<String, String>> filterApks(
|
||||||
|
List<MapEntry<String, String>> apkUrls,
|
||||||
|
String? apkFilterRegEx,
|
||||||
|
bool? invert) {
|
||||||
|
if (apkFilterRegEx?.isNotEmpty == true) {
|
||||||
|
var reg = RegExp(apkFilterRegEx!);
|
||||||
|
apkUrls = apkUrls.where((element) {
|
||||||
|
var hasMatch = reg.hasMatch(element.key);
|
||||||
|
return invert == true ? !hasMatch : hasMatch;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
return apkUrls;
|
||||||
|
}
|
||||||
|
|
||||||
class SourceProvider {
|
class SourceProvider {
|
||||||
// Add more source classes here so they are available via the service
|
// Add more source classes here so they are available via the service
|
||||||
List<AppSource> get sources => [
|
List<AppSource> get sources => [
|
||||||
@ -676,12 +744,12 @@ class SourceProvider {
|
|||||||
APKMirror(),
|
APKMirror(),
|
||||||
HuaweiAppGallery(),
|
HuaweiAppGallery(),
|
||||||
Jenkins(),
|
Jenkins(),
|
||||||
Mullvad(),
|
|
||||||
Signal(),
|
Signal(),
|
||||||
VLC(),
|
VLC(),
|
||||||
WhatsApp(),
|
WhatsApp(),
|
||||||
TelegramApp(),
|
TelegramApp(),
|
||||||
NeutronCode(),
|
NeutronCode(),
|
||||||
|
DirectAPKLink(),
|
||||||
HTML() // This should ALWAYS be the last option as they are tried in order
|
HTML() // This should ALWAYS be the last option as they are tried in order
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -697,22 +765,26 @@ class SourceProvider {
|
|||||||
throw UnsupportedURLError();
|
throw UnsupportedURLError();
|
||||||
}
|
}
|
||||||
var res = srcs.first;
|
var res = srcs.first;
|
||||||
res.host = Uri.parse(url).host;
|
res.hosts = [Uri.parse(url).host];
|
||||||
res.hostChanged = true;
|
res.hostChanged = true;
|
||||||
return srcs.first;
|
return srcs.first;
|
||||||
}
|
}
|
||||||
AppSource? source;
|
AppSource? source;
|
||||||
for (var s in sources.where((element) => element.host != null)) {
|
for (var s in sources.where((element) => element.hosts.isNotEmpty)) {
|
||||||
if (RegExp(
|
try {
|
||||||
'://${s.allowSubDomains ? '([^\\.]+\\.)*' : '(www\\.)?'}${s.host}(/|\\z)?')
|
if (RegExp(
|
||||||
.hasMatch(url)) {
|
'^${s.allowSubDomains ? '([^\\.]+\\.)*' : '(www\\.)?'}(${getSourceRegex(s.hosts)})\$')
|
||||||
source = s;
|
.hasMatch(Uri.parse(url).host)) {
|
||||||
break;
|
source = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
for (var s in sources.where(
|
for (var s in sources.where(
|
||||||
(element) => element.host == null && !element.neverAutoSelect)) {
|
(element) => element.hosts.isEmpty && !element.neverAutoSelect)) {
|
||||||
try {
|
try {
|
||||||
s.sourceSpecificStandardizeURL(url);
|
s.sourceSpecificStandardizeURL(url);
|
||||||
source = s;
|
source = s;
|
||||||
@ -747,7 +819,7 @@ class SourceProvider {
|
|||||||
AppSource source, String url, Map<String, dynamic> additionalSettings,
|
AppSource source, String url, Map<String, dynamic> additionalSettings,
|
||||||
{App? currentApp,
|
{App? currentApp,
|
||||||
bool trackOnlyOverride = false,
|
bool trackOnlyOverride = false,
|
||||||
String? overrideSource,
|
bool sourceIsOverriden = false,
|
||||||
bool inferAppIdIfOptional = false}) async {
|
bool inferAppIdIfOptional = false}) async {
|
||||||
if (trackOnlyOverride || source.enforceTrackOnly) {
|
if (trackOnlyOverride || source.enforceTrackOnly) {
|
||||||
additionalSettings['trackOnly'] = true;
|
additionalSettings['trackOnly'] = true;
|
||||||
@ -757,8 +829,9 @@ class SourceProvider {
|
|||||||
APKDetails apk =
|
APKDetails apk =
|
||||||
await source.getLatestAPKDetails(standardUrl, additionalSettings);
|
await source.getLatestAPKDetails(standardUrl, additionalSettings);
|
||||||
|
|
||||||
if (source.runtimeType != HTML().runtimeType) {
|
if (source.runtimeType !=
|
||||||
// HTML does it separately
|
HTML().runtimeType && // Some sources do it separately
|
||||||
|
source.runtimeType != SourceForge().runtimeType) {
|
||||||
String? extractedVersion = extractVersion(
|
String? extractedVersion = extractVersion(
|
||||||
additionalSettings['versionExtractionRegEx'] as String?,
|
additionalSettings['versionExtractionRegEx'] as String?,
|
||||||
additionalSettings['matchGroupToUse'] as String?,
|
additionalSettings['matchGroupToUse'] as String?,
|
||||||
@ -768,15 +841,12 @@ class SourceProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' &&
|
if (additionalSettings['releaseDateAsVersion'] == true &&
|
||||||
apk.releaseDate != null) {
|
apk.releaseDate != null) {
|
||||||
apk.version = apk.releaseDate!.microsecondsSinceEpoch.toString();
|
apk.version = apk.releaseDate!.microsecondsSinceEpoch.toString();
|
||||||
}
|
}
|
||||||
if (additionalSettings['apkFilterRegEx'] != null) {
|
apk.apkUrls = filterApks(apk.apkUrls, additionalSettings['apkFilterRegEx'],
|
||||||
var reg = RegExp(additionalSettings['apkFilterRegEx']);
|
additionalSettings['invertAPKFilter']);
|
||||||
apk.apkUrls =
|
|
||||||
apk.apkUrls.where((element) => reg.hasMatch(element.key)).toList();
|
|
||||||
}
|
|
||||||
if (apk.apkUrls.isEmpty && !trackOnly) {
|
if (apk.apkUrls.isEmpty && !trackOnly) {
|
||||||
throw NoAPKError();
|
throw NoAPKError();
|
||||||
}
|
}
|
||||||
@ -817,7 +887,9 @@ class SourceProvider {
|
|||||||
categories: currentApp?.categories ?? const [],
|
categories: currentApp?.categories ?? const [],
|
||||||
releaseDate: apk.releaseDate,
|
releaseDate: apk.releaseDate,
|
||||||
changeLog: apk.changeLog,
|
changeLog: apk.changeLog,
|
||||||
overrideSource: overrideSource ?? currentApp?.overrideSource,
|
overrideSource: sourceIsOverriden
|
||||||
|
? source.runtimeType.toString()
|
||||||
|
: currentApp?.overrideSource,
|
||||||
allowIdChange: currentApp?.allowIdChange ??
|
allowIdChange: currentApp?.allowIdChange ??
|
||||||
trackOnly ||
|
trackOnly ||
|
||||||
(source.appIdInferIsOptional &&
|
(source.appIdInferIsOptional &&
|
||||||
@ -841,6 +913,7 @@ class SourceProvider {
|
|||||||
apps.add(await getApp(
|
apps.add(await getApp(
|
||||||
source,
|
source,
|
||||||
url,
|
url,
|
||||||
|
sourceIsOverriden: sourceOverride != null,
|
||||||
getDefaultValuesFromFormItems(
|
getDefaultValuesFromFormItems(
|
||||||
source.combinedAppSpecificSettingFormItems)));
|
source.combinedAppSpecificSettingFormItems)));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
220
pubspec.lock
@ -22,10 +22,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: android_package_manager
|
name: android_package_manager
|
||||||
sha256: b873fe5856f7c442aca9751dac05d117285be9e4de08eb15d1ffb811fd1b688d
|
sha256: "2de859fae7226a7de1c1ff9a2308f1967599408800330501a1ce97927c051153"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "0.7.1"
|
||||||
animations:
|
animations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -70,10 +70,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: background_fetch
|
name: background_fetch
|
||||||
sha256: f70b28a0f7a3156195e9742229696f004ea3bf10f74039b7bf4c78a74fbda8a4
|
sha256: "34550cf9b383e5a1844e7d22119aa500508c7df9421fa967c9fb4430d6cb2878"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.2"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -150,10 +150,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: cross_file
|
name: cross_file
|
||||||
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
|
sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.3+8"
|
version: "0.3.3+7"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -190,10 +190,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: device_info_plus
|
name: device_info_plus
|
||||||
sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6"
|
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.1.1"
|
version: "9.1.2"
|
||||||
device_info_plus_platform_interface:
|
device_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -214,10 +214,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: easy_localization
|
name: easy_localization
|
||||||
sha256: de63e3b422adfc97f256cbb3f8cf12739b6a4993d390f3cadb3f51837afaefe5
|
sha256: "9c86754b22aaa3e74e471635b25b33729f958dd6fb83df0ad6612948a7b231af"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.4"
|
||||||
easy_logger:
|
easy_logger:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -238,10 +238,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.2"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -258,6 +258,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.1"
|
version: "6.1.1"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -299,10 +307,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_local_notifications
|
name: flutter_local_notifications
|
||||||
sha256: "892ada16046d641263f30c72e7432397088810a84f34479f6677494802a2b535"
|
sha256: c18f1de98fe0bb9dd5ba91e1330d4febc8b6a7de6aae3ffe475ef423723e72f3
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "16.3.0"
|
version: "16.3.2"
|
||||||
flutter_local_notifications_linux:
|
flutter_local_notifications_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -328,10 +336,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_markdown
|
name: flutter_markdown
|
||||||
sha256: "30088ce826b5b9cfbf9e8bece34c716c8a59fa54461dcae1e4ac01a94639e762"
|
sha256: "21b085a1c185e46701373866144ced56cfb7a0c33f63c916bb8fe2d0c1491278"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.18+3"
|
version: "0.6.19"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -386,10 +394,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
|
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.2.1"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -402,10 +410,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271"
|
sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.3"
|
version: "4.1.7"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -430,6 +438,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.8.1"
|
version: "4.8.1"
|
||||||
|
leak_tracker:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: leak_tracker
|
||||||
|
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "10.0.0"
|
||||||
|
leak_tracker_flutter_testing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: leak_tracker_flutter_testing
|
||||||
|
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
|
leak_tracker_testing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: leak_tracker_testing
|
||||||
|
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -442,42 +474,42 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: markdown
|
name: markdown
|
||||||
sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd
|
sha256: "1b134d9f8ff2da15cb298efe6cd8b7d2a78958c1b00384ebcbdf13fe340a6c90"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.1.1"
|
version: "7.2.1"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.16"
|
version: "0.12.16+1"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.8.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.11.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: mime
|
name: mime
|
||||||
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.5"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -498,18 +530,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.3"
|
version: "1.9.0"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
path_provider_android:
|
path_provider_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -522,10 +554,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_foundation
|
name: path_provider_foundation
|
||||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.1"
|
version: "2.3.2"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -538,10 +570,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_platform_interface
|
name: path_provider_platform_interface
|
||||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
path_provider_windows:
|
path_provider_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -554,50 +586,50 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: permission_handler
|
name: permission_handler
|
||||||
sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78"
|
sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.1.0"
|
version: "11.3.0"
|
||||||
permission_handler_android:
|
permission_handler_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_android
|
name: permission_handler_android
|
||||||
sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6"
|
sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "12.0.1"
|
version: "12.0.5"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_apple
|
name: permission_handler_apple
|
||||||
sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306"
|
sha256: bdafc6db74253abb63907f4e357302e6bb786ab41465e8635f362ee71fd8707b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.2.0"
|
version: "9.4.0"
|
||||||
permission_handler_html:
|
permission_handler_html:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_html
|
name: permission_handler_html
|
||||||
sha256: "11b762a8c123dced6461933a88ea1edbbe036078c3f9f41b08886e678e7864df"
|
sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.0+2"
|
version: "0.1.1"
|
||||||
permission_handler_platform_interface:
|
permission_handler_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_platform_interface
|
name: permission_handler_platform_interface
|
||||||
sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1
|
sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.2.0"
|
||||||
permission_handler_windows:
|
permission_handler_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_windows
|
name: permission_handler_windows
|
||||||
sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004"
|
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.1"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -626,10 +658,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pointycastle
|
name: pointycastle
|
||||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.7.3"
|
version: "3.7.4"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -642,10 +674,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share_plus
|
name: share_plus
|
||||||
sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd
|
sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.2.1"
|
version: "7.2.2"
|
||||||
share_plus_platform_interface:
|
share_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -674,10 +706,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_foundation
|
name: shared_preferences_foundation
|
||||||
sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7"
|
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.4"
|
version: "2.3.5"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -690,18 +722,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_platform_interface
|
name: shared_preferences_platform_interface
|
||||||
sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
|
sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.1"
|
version: "2.3.2"
|
||||||
shared_preferences_web:
|
shared_preferences_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_web
|
name: shared_preferences_web
|
||||||
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
|
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.2"
|
version: "2.2.1"
|
||||||
shared_preferences_windows:
|
shared_preferences_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -714,10 +746,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: shared_storage
|
name: shared_storage
|
||||||
sha256: "7c65a9d64f0f5521256be974cfd74010af12196657cec9f9fb7b03b2f11bcaf6"
|
sha256: cf20428d06af065311b71e09cbfbbfe431e979a3bf9180001c1952129b7c708f
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.0"
|
version: "0.8.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -743,18 +775,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: sqflite
|
name: sqflite
|
||||||
sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a"
|
sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.2"
|
||||||
sqflite_common:
|
sqflite_common:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqflite_common
|
name: sqflite_common
|
||||||
sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6
|
sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0+2"
|
version: "2.5.3"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -823,26 +855,26 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86
|
sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.2"
|
version: "6.2.4"
|
||||||
url_launcher_android:
|
url_launcher_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: c0766a55ab42cefaa728cabc951e82919ab41a3a4fee0aaa96176ca82da8cc51
|
sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.1"
|
version: "6.3.0"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_ios
|
name: url_launcher_ios
|
||||||
sha256: "46b81e3109cbb2d6b81702ad3077540789a3e74e22795eb9f0b7d494dbaa72ea"
|
sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.2"
|
version: "6.2.4"
|
||||||
url_launcher_linux:
|
url_launcher_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -863,18 +895,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_platform_interface
|
name: url_launcher_platform_interface
|
||||||
sha256: "4aca1e060978e19b2998ee28503f40b5ba6226819c2b5e3e4d1821e8ccd92198"
|
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.2"
|
||||||
url_launcher_web:
|
url_launcher_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_web
|
name: url_launcher_web
|
||||||
sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b
|
sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.3"
|
version: "2.2.0"
|
||||||
url_launcher_windows:
|
url_launcher_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -887,10 +919,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: uuid
|
name: uuid
|
||||||
sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f"
|
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.2"
|
version: "4.3.3"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -899,46 +931,54 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
|
vm_service:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vm_service
|
||||||
|
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "13.0.0"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: web
|
name: web
|
||||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.5.0"
|
||||||
webview_flutter:
|
webview_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: webview_flutter
|
name: webview_flutter
|
||||||
sha256: "60e23976834e995c404c0b21d3b9db37ecd77d3303ef74f8b8d7a7b19947fc04"
|
sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.4.3"
|
version: "4.7.0"
|
||||||
webview_flutter_android:
|
webview_flutter_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
sha256: "161af93c2abaf94ef2192bffb53a3658b2d721a3bf99b69aa1e47814ee18cc96"
|
sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.13.2"
|
version: "3.15.0"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_platform_interface
|
name: webview_flutter_platform_interface
|
||||||
sha256: dbe745ee459a16b6fec296f7565a8ef430d0d681001d8ae521898b9361854943
|
sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.9.0"
|
version: "2.10.0"
|
||||||
webview_flutter_wkwebview:
|
webview_flutter_wkwebview:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_wkwebview
|
name: webview_flutter_wkwebview
|
||||||
sha256: "02d8f3ebbc842704b2b662377b3ee11c0f8f1bbaa8eab6398262f40049819160"
|
sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.10.1"
|
version: "3.12.0"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -980,5 +1020,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.2.0 <4.0.0"
|
dart: ">=3.3.0 <4.0.0"
|
||||||
flutter: ">=3.16.0"
|
flutter: ">=3.16.6"
|
||||||
|
@ -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
|
# 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
|
# 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.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 0.15.6+242 # When changing this, update the tag in main() accordingly
|
version: 1.0.3+2253 # When changing this, update the tag in main() accordingly
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
@ -55,7 +55,7 @@ dependencies:
|
|||||||
git:
|
git:
|
||||||
url: https://github.com/ImranR98/android_package_installer
|
url: https://github.com/ImranR98/android_package_installer
|
||||||
ref: main
|
ref: main
|
||||||
android_package_manager: ^0.6.0
|
android_package_manager: ^0.7.0
|
||||||
share_plus: ^7.0.0
|
share_plus: ^7.0.0
|
||||||
sqflite: ^2.2.0+3
|
sqflite: ^2.2.0+3
|
||||||
easy_localization: ^3.0.1
|
easy_localization: ^3.0.1
|
||||||
|