Merge branch 'weblate' into 'master'

Weblate

Closes #1270

See merge request fdroid/fdroidclient!657
This commit is contained in:
Hans-Christoph Steiner 2018-03-20 16:56:13 +00:00
commit f52194ef7e
29 changed files with 164 additions and 80 deletions

View File

@ -29,13 +29,16 @@ import java.util.Map;
/**
* Manages the state of APKs that are being installed or that have updates available.
* This also ensures the state is saved across F-Droid restarts, and repopulates
* based on {@link org.fdroid.fdroid.data.Schema.InstalledAppTable} data, APKs that
* are present in the cache, and the {@code apks-pending-install}
* {@link SharedPreferences} instance.
* <p>
* The full URL for the APK file to download is used as the unique ID to
* represent the status of the APK throughout F-Droid. The full download URL is guaranteed
* to be unique since it points to files on a filesystem, where there cannot be multiple files with
* the same name. This provides a unique ID beyond just {@code packageName}
* and {@code versionCode} since there could be different copies of the same
* APK on different servers, signed by different keys, or even different builds.
* As defined in {@link org.fdroid.fdroid.installer.InstallManagerService}, the
* canonical URL for the APK file to download is used as the unique ID to represent
* the status of the APK throughout F-Droid.
*
* @see org.fdroid.fdroid.installer.InstallManagerService
*/
public final class AppUpdateStatusManager {
@ -370,7 +373,7 @@ public final class AppUpdateStatusManager {
public void removeApk(String key) {
synchronized (appMapping) {
AppUpdateStatus entry = appMapping.get(key);
AppUpdateStatus entry = appMapping.remove(key);
if (entry != null) {
Utils.debugLog(LOGTAG, "Remove APK " + entry.apk.apkName);
notifyRemove(entry);
@ -556,8 +559,8 @@ public final class AppUpdateStatusManager {
*
* @see #isPendingInstall(String)
*/
public void markAsPendingInstall(String uniqueKey) {
AppUpdateStatus entry = get(uniqueKey);
public void markAsPendingInstall(String urlString) {
AppUpdateStatus entry = get(urlString);
if (entry != null) {
Utils.debugLog(TAG, "Marking " + entry.apk.packageName + " as pending install.");
apksPendingInstall.edit().putBoolean(entry.apk.hash, true).apply();
@ -568,8 +571,8 @@ public final class AppUpdateStatusManager {
* @see #markAsNoLongerPendingInstall(AppUpdateStatus)
* @see #isPendingInstall(String)
*/
public void markAsNoLongerPendingInstall(String uniqueKey) {
AppUpdateStatus entry = get(uniqueKey);
public void markAsNoLongerPendingInstall(String urlString) {
AppUpdateStatus entry = get(urlString);
if (entry != null) {
markAsNoLongerPendingInstall(entry);
}

View File

@ -20,13 +20,15 @@ import java.util.ArrayList;
import java.util.List;
/**
* Scans the list of downloaded .apk files in the cache for each app which can be updated.
* If a valid .apk file is found then it will tell the {@link AppUpdateStatusManager} that it is
* {@link AppUpdateStatusManager.Status#ReadyToInstall}. This is an {@link IntentService} so as to
* run on a background thread, as it hits the disk a bit to figure out the hash of each downloaded
* file.
* Scans the list of downloaded .apk files in the cache. This info is used to
* determine if an APK is ready to install. When a valid .apk file is found,
* this checks whether that APK is already installed, and whether the user's
* install request is still active. If all those are true, then this tells the
* {@link AppUpdateStatusManager} that the APK is
* {@link AppUpdateStatusManager.Status#ReadyToInstall}. This is an
* {@link IntentService} so as to run on a background thread, as it hits the
* disk a bit to figure out the hash of each downloaded file.
*/
@SuppressWarnings("LineLength")
public class AppUpdateStatusService extends IntentService {
private static final String TAG = "AppUpdateStatusService";
@ -54,6 +56,7 @@ public class AppUpdateStatusService extends IntentService {
if (cacheDirList == null) {
return;
}
PackageManager packageManager = getPackageManager();
List<Apk> apksReadyToInstall = new ArrayList<>();
for (String repoDirName : cacheDirList) {
File repoDir = new File(cacheDir, repoDirName);
@ -64,14 +67,23 @@ public class AppUpdateStatusService extends IntentService {
for (String apkFileName : apks) {
Apk apk = processDownloadedApk(new File(repoDir, apkFileName));
if (apk != null) {
Log.i(TAG, "Found downloaded apk " + apk.packageName + ". Notifying user that it should be installed.");
PackageInfo packageInfo = null;
try {
packageInfo = packageManager.getPackageInfo(apk.packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
// ignored
}
if (packageInfo == null || packageInfo.versionCode != apk.versionCode) {
Utils.debugLog(TAG, "Marking downloaded apk " + apk.apkName + " as ReadyToInstall");
apksReadyToInstall.add(apk);
}
}
}
}
if (apksReadyToInstall.size() > 0) {
AppUpdateStatusManager.getInstance(this).addApks(apksReadyToInstall, AppUpdateStatusManager.Status.ReadyToInstall);
AppUpdateStatusManager.getInstance(this).addApks(apksReadyToInstall,
AppUpdateStatusManager.Status.ReadyToInstall);
InstallManagerService.managePreviouslyDownloadedApks(this);
}
}
@ -100,21 +112,25 @@ public class AppUpdateStatusService extends IntentService {
return null;
}
PackageInfo downloadedInfo = getPackageManager().getPackageArchiveInfo(apkPath.getAbsolutePath(), PackageManager.GET_GIDS);
PackageInfo downloadedInfo = getPackageManager().getPackageArchiveInfo(apkPath.getAbsolutePath(),
PackageManager.GET_GIDS);
if (downloadedInfo == null) {
Log.i(TAG, "Skipping " + apkPath + " because PackageManager was unable to read it.");
return null;
}
Utils.debugLog(TAG, "Found package for " + downloadedInfo.packageName + ", checking its hash to see if it downloaded correctly.");
Utils.debugLog(TAG, "Found package for " + downloadedInfo.packageName + ':' + downloadedInfo.versionCode
+ ", checking its hash to see if it downloaded correctly.");
Apk downloadedApk = findApkMatchingHash(apkPath);
if (downloadedApk == null) {
Log.i(TAG, "Either the apk wasn't downloaded fully, or the repo it came from has been disabled. Either way, not notifying the user about it.");
Log.i(TAG, "Either the apk wasn't downloaded fully, or the repo it came from has been disabled. "
+ "Either way, not notifying the user about it.");
return null;
}
if (!AppUpdateStatusManager.getInstance(this).isPendingInstall(downloadedApk.hash)) {
Log.i(TAG, downloadedApk.packageName + " is NOT pending install, probably just left over from a previous install.");
Log.i(TAG, downloadedApk.packageName + ':' + downloadedApk.versionCode
+ " is NOT pending install, probably just left over from a previous install.");
return null;
}
@ -124,14 +140,16 @@ public class AppUpdateStatusService extends IntentService {
if (pathToInstalled != null && pathToInstalled.canRead() &&
pathToInstalled.length() == downloadedApk.size && // Check size before hash for performance.
TextUtils.equals(Utils.getBinaryHash(pathToInstalled, "sha256"), downloadedApk.hash)) {
Log.i(TAG, downloadedApk.packageName + " is pending install, but we already have the correct version installed.");
Log.i(TAG, downloadedApk.packageName
+ " is pending install, but we already have the correct version installed.");
AppUpdateStatusManager.getInstance(this).markAsNoLongerPendingInstall(downloadedApk.getUrl());
return null;
}
} catch (PackageManager.NameNotFoundException ignored) {
}
Utils.debugLog(TAG, downloadedApk.packageName + " is pending install, so we need to notify the user about installing it.");
Utils.debugLog(TAG, downloadedApk.packageName + ':' + downloadedApk.versionCode
+ " is pending install, so we need to notify the user about installing it.");
return downloadedApk;
}

View File

@ -40,7 +40,7 @@ import java.io.IOException;
* and then redeliver the {@link Intent} for us, which includes all of the data needed
* for {@code InstallManagerService} to do its job for the whole lifecycle of an install.
* <p>
* The full URL for the APK file to download is also used as the unique ID to
* The canonical URL for the APK file to download is also used as the unique ID to
* represent the download itself throughout F-Droid. This follows the model
* of {@link Intent#setData(Uri)}, where the core data of an {@code Intent} is
* a {@code Uri}. The full download URL is guaranteed to be unique since it

View File

@ -732,10 +732,11 @@ public class AppDetailsRecyclerViewAdapter
@Override
public void bindModel() {
Context context = headerView.getContext();
if (hasCompatibleApksDifferentSigs()) {
headerView.setText("No versions with compatible signature");
headerView.setText(context.getString(R.string.app_details__no_versions__no_compatible_signatures));
} else {
headerView.setText("No versions compatible with device");
headerView.setText(context.getString(R.string.app_details__no_versions__none_compatible_with_device));
}
}

View File

@ -17,10 +17,6 @@ public class DismissResult {
this(null, false);
}
public DismissResult(boolean requiresAdapterRefresh) {
this(null, requiresAdapterRefresh);
}
public DismissResult(@Nullable CharSequence message, boolean requiresAdapterRefresh) {
this.message = message;
this.requiresAdapterRefresh = requiresAdapterRefresh;

View File

@ -147,7 +147,7 @@
<string name="appcompatibility">توافق التطبيق</string>
<string name="show_incompat_versions">إصدارات غير متوافقة</string>
<string name="show_incompat_versions_on">إظهار إصدارات التطبيق غير متوافقة مع الجهاز</string>
<string name="show_incompat_versions_on">إظهار إصدارات التطبيق غير المتوافقة مع الجهاز</string>
<string name="rooted">تجاهل صلاحيات الجذر</string>
<string name="rooted_on">لا تخفي أصل التطبيقات التي تتطلب امتيازات الجذر</string>
<string name="force_touch_apps">تجاهل الشاشات التي تعمل باللمس</string>
@ -518,4 +518,9 @@
<string name="panic_hide_title">إخفاء %s</string>
<string name="panic_hide_summary">التطبيق سوف يخفي نفسه</string>
<string name="menu_liberapay">Liberapay</string>
<string name="panic_hide_warning_title">تذكر كيفية الإسترجاع</string>
<string name="hiding_calculator">الحاسبة</string>
<string name="hiding_dialog_title">إخفاء %s الآن</string>
</resources>

View File

@ -587,4 +587,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Ваша камеры не падтрымлівае аўтафокус. Сканаванне кода можа быць абцяжаранае.</string>
</resources>

View File

@ -557,4 +557,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Vypadá to, že váš fotoaparát nemá automatické zaostřování. Oskenování kódu může být obtížné.</string>
</resources>

View File

@ -552,4 +552,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="panic_hide_warning_title">Sicherungsmethode beibehalten</string>
<string name="warning_scaning_qr_code">Ihre Kamera scheint keinen Autofokus zu haben. Es könnte schwierig sein, den Code zu scannen.</string>
</resources>

View File

@ -535,4 +535,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Via fotilo ne havas memfokuson. Povas esti malfacile skani la kodon.</string>
</resources>

View File

@ -80,8 +80,7 @@
<string name="search_hint">Buscar aplicaciones</string>
<string name="appcompatibility">Compatibilidad de aplicaciones</string>
<string name="show_incompat_versions">Versiones incompatibles</string>
<string name="show_incompat_versions_on">Mostrar las versiones de aplicaciones incompatibles con el dispositivo
</string>
<string name="show_incompat_versions_on">Mostrar las versiones incompatibles de las aplicaciones</string>
<string name="rooted">Obviar permisos de administración</string>
<string name="rooted_on">No marcar en gris las aplicaciones que piden permisos de administración<i>root</i>)</string>
<string name="force_touch_apps">Ignorar pantalla táctil</string>
@ -336,7 +335,7 @@
<string name="menu_email">Escribir al autor por correo electrónico</string>
<string name="swap_stopping_wifi">Deteniendo la Wi-Fi…</string>
<string name="useTor">Usar Tor</string>
<string name="useTorSummary">Forzar el tráfico de bajada a través de Tor para mejorar la privacidad. Requiere Orbot</string>
<string name="useTorSummary">Forzar el tráfico de descarga a través de Tor para mejorar la privacidad. Requiere Orbot</string>
<string name="repo_provider">Repositorio: %s</string>
<string name="update_auto_download">Obtenga actualizaciones automáticamente</string>
@ -540,4 +539,19 @@
<string name="panic_hide_title">Ocultar %s</string>
<string name="panic_hide_summary">La aplicación se ocultará</string>
<string name="sort_search">Ordenar resultados</string>
<string name="menu_liberapay">Liberapay</string>
<string name="panic_hide_warning_title">Recordar cómo restaurar</string>
<string name="panic_hide_warning_message">En un momento de pánico, se eliminará %1$s de la pantalla de inicio. Solo se restaurará escribiendo \"%2$d\" en la apli falsa %3$s.</string>
<string name="hiding_calculator">Calculadora</string>
<string name="hiding_dialog_title">Ocultar %s ahora</string>
<string name="hiding_dialog_message">¿Seguro que quieres eliminar %1$s de la pantalla de inicio? Solo se restaurará escribiendo \"%2$d\" en la apli falsa %3$s.</string>
<string name="hiding_dialog_warning">Atención: se eliminará también cualquier atajo de la aplicación en la pantalla de inicio y tendrá que añadirse manualmente.</string>
<string name="hide_on_long_search_press_title">Ocultar con el botón de búsqueda</string>
<string name="hide_on_long_search_press_summary">Manteniendo pulsado el botón de búsqueda se ocultará la aplicación</string>
<string name="warning_scaning_qr_code">Parece que tu cámara no tiene autoenfoque. Puede resultar difícil escanear el código.</string>
</resources>

View File

@ -546,4 +546,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Su kaameral ei paista olevat automaatfokusseerimist. Koodi skannimine võib olla keeruline.</string>
</resources>

View File

@ -573,4 +573,5 @@
<string name="sort_search">Ordenatu bilaketa</string>
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Zure kamerak ez du fokatze automatikorako gaitasunik. Kodea eskaneatzea zaila izan daiteke.</string>
</resources>

View File

@ -517,4 +517,5 @@
<string name="menu_liberapay">لیبراپی</string>
<string name="warning_scaning_qr_code">به نظر نمی‌رسد دوربینتان از تمرکز خودکار پشتیبانی کند. ممکن است پویش رمز سخت باشد.</string>
</resources>

View File

@ -557,4 +557,5 @@
<string name="hide_on_long_search_press_title">Cacher à l\'aide du bouton de recherche</string>
<string name="hide_on_long_search_press_summary">Appuyez longuement sur le bouton de recherche pour cacher l\'application</string>
<string name="warning_scaning_qr_code">Votre appareil-photo na pas de mise au point automatique. Il sera peut-être difficile de scanner le code.</string>
</resources>

View File

@ -543,4 +543,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">כנראה שלמצלמה שלך אין מיקוד אוטומטי. סריקת הקוד עשויה להוות מכשול.</string>
</resources>

View File

@ -586,4 +586,5 @@
<string name="sort_search">Raða leit</string>
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Það lítur út eins og myndavélin þín sé ekki með sjálfvirkan fókus. Það gæti orðið vandkvæðum bundið að skanna kóðann.</string>
</resources>

View File

@ -76,10 +76,10 @@
<string name="appcompatibility">アプリの互換性</string>
<string name="show_incompat_versions">互換性の無いバージョン</string>
<string name="show_incompat_versions_on">端末と互換性のないバージョンを表示します</string>
<string name="rooted">rootアプリを無視する</string>
<string name="rooted">rootアプリ</string>
<string name="rooted_on">root権限を要求するアプリを表示します</string>
<string name="force_touch_apps">タッチスクリーンを無視する</string>
<string name="force_touch_apps_on">タッチスクリーンを要求するアプリを常に表示します</string>
<string name="force_touch_apps">タッチスクリーンを使用するアプリ</string>
<string name="force_touch_apps_on">ハードウェアでサポートされていない場合でも、タッチスクリーンの使用を要求するアプリを表示します</string>
<string name="local_repo">ローカルリポジトリ</string>
<string name="local_repo_running">F-Droidは交換の準備ができました</string>
<string name="touch_to_configure_local_repo">タッチすると詳細を表示し、アプリの交換ができるようになります。</string>
@ -143,8 +143,8 @@
<string name="category_Security">セキュリティ</string>
<string name="category_System">システム</string>
<string name="requesting_root_access_body">root権限の要求中</string>
<string name="root_access_denied_title">root権限での接続が拒絶されました</string>
<string name="root_access_denied_body">この端末はroot化されていないか、F-Droidのrootアクセスが拒絶されました。</string>
<string name="root_access_denied_title">rootへのアクセスが拒否されました</string>
<string name="root_access_denied_body">この端末はroot化されていないか、F-Droidのrootへのアクセスが拒否されました。</string>
<string name="swap_nfc_description">友だちがF-DroidとNFCを持っているなら、一緒にお使いの端末をタッチしてください。</string>
<string name="swap_join_same_wifi">友達として同じWi-Fiに参加</string>
<string name="swap">アプリの交換</string>
@ -324,8 +324,8 @@
<string name="installing">インストール中</string>
<string name="uninstalling">アンインストール中</string>
<string name="hide_anti_feature_apps">対策機能のアプリををグレーアウト</string>
<string name="hide_anti_feature_apps_on">対策機能を必要とするアプリを隠します</string>
<string name="hide_anti_feature_apps">好ましくない機能を使用するアプリ</string>
<string name="hide_anti_feature_apps_on">好ましくない機能の使用を必要とするアプリを隠します</string>
<string name="update_auto_install">自動的に更新をインストール</string>
<string name="update_auto_install_summary">バックグラウンドでアプリのアップデートをダウンロードしてインストールします</string>
<string name="keep_install_history">インストール履歴を保存する</string>
@ -402,7 +402,7 @@
<string name="details_new_in_version">バージョン%sの新機能</string>
<string name="antifeatureswarning">このアプリは好ましくない機能を含んでいるかもしれません。</string>
<string name="antifeatures">対策機能</string>
<string name="antifeatures">好ましくない機能</string>
<plurals name="details_last_update_days">
<item quantity="other">%1$d日前に更新しました</item>
</plurals>
@ -465,10 +465,10 @@
<string name="updates__app_with_known_vulnerability__ignore">無視する</string>
<string name="privacy">プライバシー</string>
<string name="preventScreenshots_title">スクリーンショット防止</string>
<string name="preventScreenshots_title">スクリーンショット防止</string>
<string name="preventScreenshots_summary">スクリーンショットの撮影を防止するとともに、アプリ履歴にアプリの内容が表示されないようにします</string>
<string name="panic_app_setting_title">パニックボタンアプリ</string>
<string name="panic_app_setting_title">パニックボタンアプリ</string>
<string name="panic_app_unknown_app">不明のアプリ</string>
<string name="panic_app_setting_summary">アプリが設定されていません</string>
<string name="panic_app_setting_none">なし</string>
@ -476,7 +476,7 @@
<string name="panic_app_dialog_message">%1$sを破壊的なパニックボタンとして動作させることを許可してもよろしいですか</string>
<string name="allow">許可</string>
<string name="panic_settings">パニックボタン設定</string>
<string name="panic_settings">パニックボタン設定</string>
<string name="panic_settings_summary">緊急時のアクション</string>
<string name="panic_exit_title">アプリを終了</string>
<string name="panic_exit_summary">アプリを閉じます</string>
@ -497,4 +497,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">お使いのカメラはオートフォーカスがないようです。コードをスキャンするのが難しいことがあるかもしれません。</string>
</resources>

View File

@ -544,4 +544,9 @@
<string name="hide_on_long_search_press_title">Skjul med søke-knappen</string>
<string name="hide_on_long_search_press_summary">Å trykke lenge på søkeknappen vil skjule programmet</string>
<string name="sort_search">Sorter søk</string>
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Kameraet ditt mangler autofokus. Det kan vise seg vanskelig å skanne koden.</string>
</resources>

View File

@ -534,4 +534,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Je camera lijkt niet over autofocus te beschikken. Het scannen van de code kan moeilijk zijn.</string>
</resources>

View File

@ -564,4 +564,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Twój aparat nie posiada autofokusu. Mogą wystąpić trudności ze zeskanowaniem kodu.</string>
</resources>

View File

@ -560,4 +560,9 @@
<string name="hide_on_long_search_press_title">Esconder o botão de busca</string>
<string name="hide_on_long_search_press_summary">Pressionar o botão de busca por um tempo longo vai esconder o app</string>
<string name="sort_search">Classificação da pesquisa</string>
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Sua câmera não parece ter focagem automática. Pode ser difícil escanear o código.</string>
</resources>

View File

@ -510,4 +510,5 @@
<string name="hiding_dialog_message">Sigur doriți să eliminați %1$s din lansator? Doar scriind \"%2$d\" în aplicația falsă %3$s veți putea să o restaurați.</string>
<string name="hiding_dialog_warning">Atenție: Orice scurtătură din ecranul de pornire va fi de asemenea eliminată și va trebui adăugată din nou manual.</string>
<string name="hide_on_long_search_press_summary">Aplicația va fi ascunsă dacă se apasă lung butonul de căutare</string>
<string name="warning_scaning_qr_code">Camera foto a dispozitivului nu pare să suporte focalizare automată. Ar putea fi dificil să se scaneze codul.</string>
</resources>

View File

@ -545,4 +545,5 @@
<string name="hide_on_long_search_press_title">Скрыть с помощью кнопки поиска</string>
<string name="hide_on_long_search_press_summary">Длительное нажатие кнопки поиска скроет приложение</string>
<string name="warning_scaning_qr_code">Ваша камера не поддерживает автофокус. Сканирование кода может быть затруднено.</string>
</resources>

View File

@ -562,11 +562,11 @@
<string name="panic_hide_summary">S\'aplicatzione s\'at a istichire</string>
<string name="panic_hide_warning_title">Ammenta comente ripristinare</string>
<string name="panic_hide_warning_message">In casu de un\'eventu de pànicu, custu at a bogare %1$s dae su \"launcher\". Petzi incarchende \"%2$d\" in s\'aplicatzione frassa %3$s l\'as a pòdere ripristinare.</string>
<string name="panic_hide_warning_message">In casu de un\'eventu de pànicu, custu at a bogare %1$s dae su \"launcher\" (s\'afiladore). Petzi incarchende \"%2$d\" in s\'aplicatzione frassa %3$s l\'as a pòdere ripristinare.</string>
<string name="hiding_calculator">Calcolatrice</string>
<string name="hiding_dialog_title">Istichi %s como</string>
<string name="hiding_dialog_message">Seguru ses de chèrrere bogare %1$s dae su \"launcher\"? Petzi incarchende \"%2$d\" in s\'aplicatzione frassa %3$s l\'as a pòdere ripristinare.</string>
<string name="hiding_dialog_message">Seguru ses de chèrrere bogare %1$s dae su \"launcher\" (s\'afiladore)? Petzi incarchende \"%2$d\" in s\'aplicatzione frassa %3$s l\'as a pòdere ripristinare.</string>
<string name="hiding_dialog_warning">Atentzione: Fintzas cale si siat incurtzada in s\'ischermada printzipale at a èssere bogada e b\'at a dèpere èssere torrada a pònnere manualmente.</string>
<string name="hide_on_long_search_press_title">Istichi cun su butone de chirca</string>
<string name="hide_on_long_search_press_summary">Un\'incarcada longa in su butone de chirca at a istichire s\'aplicatzione</string>
@ -574,4 +574,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Paret chi sa fotocàmera tua non tèngiat su focus automàticu. Diat pòdere èssere difìtzile a iscansire su còdighe.</string>
</resources>

View File

@ -544,4 +544,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">Kameranızın kendiliğinden odaklanması yok gibi görünüyor. Kodu taramak zor olabilir.</string>
</resources>

View File

@ -214,7 +214,7 @@
<string name="display">Вигляд</string>
<string name="show_incompat_versions">Несумісні версії</string>
<string name="show_incompat_versions_on">Показувати версії застосунків, які несумісні з пристроєм</string>
<string name="show_incompat_versions_on">Показувати версії застосунків, які несумісні з цим пристроєм</string>
<string name="local_repo_running">F-Droid готовий до обміну</string>
<string name="writing_index_jar">Запис підписаного файлу індексу (index.jar)…</string>
<string name="linking_apks">Включення APK-файлів до репозиторію…</string>
@ -528,4 +528,22 @@
<string name="panic_exit_title">Вийти з додатку</string>
<string name="panic_hide_title">Приховати %s</string>
<string name="sort_search">Розсортувати за пошуком</string>
<string name="menu_liberapay">Liberapay</string>
<string name="preventScreenshots_summary">Блокує знімки екрану та приховує вміст з останніх додатків</string>
<string name="panic_app_setting_title">Вибір тривожної кнопки</string>
<string name="panic_app_dialog_title">Підтвердити тривожну кнопку</string>
<string name="panic_app_dialog_message">Ви впевнені, що бажаєте дозволити %1$s виконувати дію тривожної кнопки?</string>
<string name="panic_settings">Налаштування тривожної кнопки</string>
<string name="panic_settings_summary">Заходи, які необхідно прийняти в екстерних випадках</string>
<string name="panic_exit_summary">Додаток буде закрито</string>
<string name="panic_destructive_actions">Деструктивні дії</string>
<string name="panic_hide_summary">Додаток приховає себе</string>
<string name="panic_hide_warning_title">Запам\'ятайте, як відновити</string>
<string name="hiding_calculator">Калькулятор</string>
<string name="hiding_dialog_title">Приховати %s зараз</string>
<string name="hide_on_long_search_press_title">Приховати за допомогою кнопки пошуку</string>
</resources>

View File

@ -72,8 +72,8 @@
<string name="show_incompat_versions_on">显示与该设备不兼容的应用程序版本</string>
<string name="rooted">忽略 root</string>
<string name="rooted_on">不以灰色显示需要 root 权限的应用程序</string>
<string name="force_touch_apps">忽略触屏应用</string>
<string name="force_touch_apps_on">总是包含需要触屏的应用程序</string>
<string name="force_touch_apps">包含触屏应用</string>
<string name="force_touch_apps_on">总是展示需要触屏的应用程序,无论硬件是否支持</string>
<string name="local_repo">本地软件源</string>
<string name="deleting_repo">正在删除当前软件源…</string>
<string name="icon">图标</string>
@ -346,7 +346,7 @@
<string name="notification_title_single_update_available">可更新</string>
<string name="notification_title_summary_install_error">安装失败</string>
<string name="app_details_donate_prompt_unknown_author">给%1$s的开发者买一杯咖啡吧</string>
<string name="app_details_donate_prompt">%2$s是%1$s的开发者给他們买一杯咖啡吧!</string>
<string name="app_details_donate_prompt">%2$s 是 %1$s 的开发者,给他们买一杯咖啡吧!</string>
<string name="app_version_x_available">版本%1$s可用</string>
<string name="app_version_x_installed">版本%1$s</string>
@ -485,13 +485,14 @@
<string name="panic_app_dialog_title">确认紧急应用</string>
<string name="panic_destructive_actions">危险动作</string>
<string name="panic_hide_warning_title">请记住如何还原</string>
<string name="panic_hide_warning_message">在紧急情况下,这从启动器中移除 %1$s。只有在假的 %3$s 应用中输入“%2$d”才能恢复它。</string>
<string name="panic_hide_warning_message">在紧急情况下,这从启动器中移除 %1$s。只有在假的 %3$s 应用中输入“%2$d”才能恢复它。</string>
<string name="hiding_calculator">计算器</string>
<string name="hiding_dialog_title">立即隐藏 %s</string>
<string name="hiding_dialog_message">确定要从启动器中移除 %1$s 吗?只有在假的 %3$s 应用中输入“%2$d”才能恢复它。</string>
<string name="hiding_dialog_warning">警告:主屏幕上的任何应用捷径也将被移除,需要手动重新添加。</string>
<string name="hiding_dialog_warning">警告:主屏幕上的任何应用快捷方式也将被移除,需要手动重新添加。</string>
<string name="hide_on_long_search_press_title">用搜索按钮隐藏</string>
<string name="hide_on_long_search_press_summary">长按搜索按钮将隐藏此应用</string>
<string name="warning_scaning_qr_code">您的相机似乎没有自动对焦。扫描二维码可能较为困难。</string>
</resources>

View File

@ -510,4 +510,5 @@
<string name="menu_liberapay">Liberapay</string>
<string name="warning_scaning_qr_code">您的相機似乎沒有自動對焦。掃描代碼可能會很困難。</string>
</resources>