diff options
167 files changed, 4607 insertions, 750 deletions
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp index a0eb54754..0a1b25f3a 100644 --- a/jni/FuseDaemon.cpp +++ b/jni/FuseDaemon.cpp @@ -103,7 +103,9 @@ const bool IS_OS_DEBUGABLE = android::base::GetIntProperty("ro.debuggable", 0); // Stolen from: android_filesystem_config.h #define AID_APP_START 10000 -constexpr size_t MAX_READ_SIZE = 128 * 1024; +#define FUSE_MAX_MAX_PAGES 256 + +const size_t MAX_READ_SIZE = FUSE_MAX_MAX_PAGES * getpagesize(); // Stolen from: UserHandle#getUserId constexpr int PER_USER_RANGE = 100000; @@ -2590,7 +2592,7 @@ std::string deriveVolumeName(const std::string& path) { void FuseDaemon::DeleteFromLevelDb(const std::string& key) { std::string volume_name = deriveVolumeName(key); if (!CheckLevelDbConnection(volume_name)) { - LOG(ERROR) << "Failure in leveldb delete in volume:" << volume_name << " for key:" << key; + LOG(ERROR) << "DeleteFromLevelDb: Missing leveldb connection."; return; } @@ -2605,7 +2607,7 @@ void FuseDaemon::DeleteFromLevelDb(const std::string& key) { void FuseDaemon::InsertInLevelDb(const std::string& key, const std::string& value) { std::string volume_name = deriveVolumeName(key); if (!CheckLevelDbConnection(volume_name)) { - LOG(ERROR) << "Failure in leveldb insert in volume:" << volume_name << " for key:" << key; + LOG(ERROR) << "InsertInLevelDb: Missing leveldb connection."; return; } @@ -2613,6 +2615,7 @@ void FuseDaemon::InsertInLevelDb(const std::string& key, const std::string& valu status = fuse->level_db_connection_map[volume_name]->Put(leveldb::WriteOptions(), key, value); if (!status.ok()) { LOG(ERROR) << "Failure in leveldb insert for key: " << key << " in volume:" << volume_name; + LOG(ERROR) << status.ToString(); } } @@ -2623,7 +2626,7 @@ std::vector<std::string> FuseDaemon::ReadFilePathsFromLevelDb(const std::string& std::vector<std::string> file_paths; if (!CheckLevelDbConnection(volume_name)) { - LOG(ERROR) << "Failure in leveldb file paths read for volume:" << volume_name; + LOG(ERROR) << "ReadFilePathsFromLevelDb: Missing leveldb connection."; return file_paths; } @@ -2648,16 +2651,16 @@ std::string FuseDaemon::ReadBackedUpDataFromLevelDb(const std::string& filePath) std::string data = ""; std::string volume_name = deriveVolumeName(filePath); if (!CheckLevelDbConnection(volume_name)) { - LOG(ERROR) << "Failure in leveldb data read for key:" << filePath; + LOG(ERROR) << "ReadBackedUpDataFromLevelDb: Missing leveldb connection."; return data; } leveldb::Status status = fuse->level_db_connection_map[volume_name]->Get(leveldb::ReadOptions(), filePath, &data); - if (!status.ok()) { - LOG(WARNING) << "Failure in leveldb read for key: " << filePath << status.ToString(); - } else { - LOG(DEBUG) << "Read successful for key: " << filePath; + if (status.IsNotFound()) { + LOG(VERBOSE) << "Key is not found in leveldb: " << filePath << " " << status.ToString(); + } else if (!status.ok()) { + LOG(WARNING) << "Failure in leveldb read for key: " << filePath << " " << status.ToString(); } return data; } @@ -2665,22 +2668,26 @@ std::string FuseDaemon::ReadBackedUpDataFromLevelDb(const std::string& filePath) std::string FuseDaemon::ReadOwnership(const std::string& key) { // Return empty string if key not found std::string data = ""; - if (CheckLevelDbConnection(OWNERSHIP_RELATION)) { - leveldb::Status status = fuse->level_db_connection_map[OWNERSHIP_RELATION]->Get( - leveldb::ReadOptions(), key, &data); - if (!status.ok()) { - LOG(WARNING) << "Failure in leveldb read for key: " << key << status.ToString(); - } else { - LOG(DEBUG) << "Read successful for key: " << key; - } + if (!CheckLevelDbConnection(OWNERSHIP_RELATION)) { + LOG(ERROR) << "ReadOwnership: Missing leveldb connection."; + return data; } + + leveldb::Status status = fuse->level_db_connection_map[OWNERSHIP_RELATION]->Get( + leveldb::ReadOptions(), key, &data); + if (status.IsNotFound()) { + LOG(VERBOSE) << "Key is not found in leveldb: " << key << " " << status.ToString(); + } else if (!status.ok()) { + LOG(WARNING) << "Failure in leveldb read for key: " << key << " " << status.ToString(); + } + return data; } void FuseDaemon::CreateOwnerIdRelation(const std::string& ownerId, const std::string& ownerPackageIdentifier) { if (!CheckLevelDbConnection(OWNERSHIP_RELATION)) { - LOG(ERROR) << "Failure in leveldb insert for ownership relation."; + LOG(ERROR) << "CreateOwnerIdRelation: Missing leveldb connection."; return; } @@ -2703,7 +2710,7 @@ void FuseDaemon::CreateOwnerIdRelation(const std::string& ownerId, void FuseDaemon::RemoveOwnerIdRelation(const std::string& ownerId, const std::string& ownerPackageIdentifier) { if (!CheckLevelDbConnection(OWNERSHIP_RELATION)) { - LOG(ERROR) << "Failure in leveldb delete for ownership relation."; + LOG(ERROR) << "RemoveOwnerIdRelation: Missing leveldb connection."; return; } @@ -2729,7 +2736,7 @@ void FuseDaemon::RemoveOwnerIdRelation(const std::string& ownerId, std::map<std::string, std::string> FuseDaemon::GetOwnerRelationship() { std::map<std::string, std::string> resultMap; if (!CheckLevelDbConnection(OWNERSHIP_RELATION)) { - LOG(ERROR) << "Failure in leveldb read for ownership relation."; + LOG(ERROR) << "GetOwnerRelationship: Missing leveldb connection."; return resultMap; } diff --git a/res/drawable/error_icon.xml b/res/drawable/error_icon.xml new file mode 100644 index 000000000..e9433b758 --- /dev/null +++ b/res/drawable/error_icon.xml @@ -0,0 +1,17 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <group> + <clip-path + android:pathData="M0,0h24v24h-24z"/> + <path + android:pathData="M1,21L12,2L23,21H1ZM4.45,19H19.55L12,6L4.45,19ZM12,18C12.283,18 + 12.517,17.908 12.7,17.725C12.9,17.525 13,17.283 13,17C13,16.717 12.9,16.483 + 12.7,16.3C12.517,16.1 12.283,16 12,16C11.717,16 11.475,16.1 11.275,16.3C11.092,16.483 + 11,16.717 11,17C11,17.283 11.092,17.525 11.275,17.725C11.475,17.908 11.717,18 12, + 18ZM11,15H13V10H11V15Z" + android:fillColor="#775A0B"/> + </group> +</vector> diff --git a/res/drawable/ic_background_circle.xml b/res/drawable/ic_background_circle.xml new file mode 100644 index 000000000..ec6f524fc --- /dev/null +++ b/res/drawable/ic_background_circle.xml @@ -0,0 +1,20 @@ +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <solid android:color="?attr/categoryDefaultThumbnailCircleColor" /> +</shape>
\ No newline at end of file diff --git a/res/drawable/picker_app_icon.xml b/res/drawable/picker_app_icon.xml new file mode 100644 index 000000000..9f8334423 --- /dev/null +++ b/res/drawable/picker_app_icon.xml @@ -0,0 +1,26 @@ +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M8,2H20C21.1,2 22,2.9 22,4V16C22,17.1 21.1,18 20,18H8C6.9,18 6,17.1 6,16V4C6,2.9 6.9,2 8,2ZM20,16V4H8V16H20ZM2,6V20C2,21.1 2.9,22 4,22H18V20H4V6H2ZM13.17,13.98L15.67,11L19,15H9L11.5,11.8L13.17,13.98Z" + android:fillColor="#5F6368" + android:fillType="evenOdd"/> +</vector> diff --git a/res/drawable/thumbnail_favorites.xml b/res/drawable/thumbnail_favorites.xml new file mode 100644 index 000000000..a1a8101fe --- /dev/null +++ b/res/drawable/thumbnail_favorites.xml @@ -0,0 +1,25 @@ +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M14.81,8.62L22,9.24L16.55,13.97L18.18,21L12,17.27L5.82,21L7.46,13.97L2,9.24L9.19,8.63L12,2L14.81,8.62ZM8.24,17.67L12,15.4L15.77,17.68L14.77,13.4L18.09,10.52L13.71,10.14L12,6.1L10.3,10.13L5.92,10.51L9.24,13.39L8.24,17.67Z" + android:fillColor="#5B631D" + android:fillType="evenOdd"/> +</vector> diff --git a/res/drawable/thumbnail_videos.xml b/res/drawable/thumbnail_videos.xml new file mode 100644 index 000000000..e5944d5c7 --- /dev/null +++ b/res/drawable/thumbnail_videos.xml @@ -0,0 +1,26 @@ +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M18,6V10.48L22,6.5V17.5L18,13.52V18C18,19.1 17.1,20 16,20H4C2.9,20 2,19.1 2,18V6C2,4.9 2.9,4 4,4H16C17.1,4 18,4.9 18,6ZM16,6H4V18H16V6Z" + android:fillColor="#5B631D" + android:fillType="evenOdd"/> +</vector> + diff --git a/res/layout/error_dialog.xml b/res/layout/error_dialog.xml new file mode 100644 index 000000000..5fa23d171 --- /dev/null +++ b/res/layout/error_dialog.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="20dp" + android:gravity="center"> + <ImageView + android:layout_width="34dp" + android:layout_height="34dp" + android:src="@drawable/error_icon" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="16dp" + android:importantForAccessibility="no"/> + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/dialog_error_title" + android:textSize="24sp" + android:layout_gravity="center_horizontal" + android:gravity="center" + android:textColor="?android:attr/textColorPrimary"/> + + <TextView + android:id="@+id/message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/dialog_error_message" + android:layout_marginTop="16dp" + android:layout_gravity="center_horizontal" + android:gravity="center" + android:textSize="16sp" + android:textColor="?android:attr/textColorSecondary"/> + + <Button + android:id="@+id/okButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/dialog_button_text" + android:layout_marginTop="16dp" + android:layout_gravity="end" + android:textColor="?attr/pickerHighlightTextColor" + android:backgroundTint="?attr/pickerHighlightColor"/> +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/item_album_grid.xml b/res/layout/item_album_grid.xml index 0e67c5740..c09beaf0e 100644 --- a/res/layout/item_album_grid.xml +++ b/res/layout/item_album_grid.xml @@ -38,6 +38,16 @@ android:scaleType="centerCrop" android:contentDescription="@null"/> + <ImageView + android:id="@+id/icon_default_thumbnail" + android:layout_width="56dp" + android:layout_height="56dp" + android:scaleType="centerCrop" + android:tint="?attr/categoryDefaultThumbnailColor" + android:contentDescription="@null" + android:layout_gravity="center" + android:background="@drawable/ic_background_circle" + android:padding="16dp"/> </com.google.android.material.card.MaterialCardView> <TextView diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index c5a67ec51..7f2e20848 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Plaaslike berging"</string> <string name="app_label" msgid="9035307001052716210">"Mediaberging"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Mediakieser"</string> <string name="artist_label" msgid="8105600993099120273">"Kunstenaar"</string> <string name="unknown" msgid="2059049215682829375">"Onbekend"</string> <string name="root_images" msgid="5861633549189045666">"Prente"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Kry toegang tot wolkmedia vanaf"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Geen"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Kon nie wolkmedia-app op dié tydstip verander nie."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Mediakieser"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Mediakieser"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sinkroniseer tans media …"</string> <string name="add" msgid="2894574044585549298">"Voeg by"</string> <string name="deselect" msgid="4297825044827769490">"Ontkies"</string> <string name="deselected" msgid="8488133193326208475">"Ontkies"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Gaan jou internetverbinding na en probeer weer"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Herprobeer"</string> <string name="not_selected" msgid="2244008151669896758">"nie gekies nie"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Berei tans jou geselekteerde media voor"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> van <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> is gereed"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Gerugsteunde foto\'s word nou ingesluit"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Jy kan foto\'s van <xliff:g id="APP_NAME">%1$s</xliff:g>-rekening <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> af kies"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Kies app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Kies rekening"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Verander rekening"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Kry tans al jou foto’s"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Laat <xliff:g id="APP_NAME_0">^1</xliff:g> toe om hierdie oudiolêer te wysig?}other{Laat <xliff:g id="APP_NAME_1">^1</xliff:g> toe om <xliff:g id="COUNT">^2</xliff:g> oudiolêers te wysig?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Wysig tans oudiolêer …}other{Wysig tans <xliff:g id="COUNT">^1</xliff:g> oudiolêers …}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Laat <xliff:g id="APP_NAME_0">^1</xliff:g> toe om hierdie video te wysig?}other{Laat <xliff:g id="APP_NAME_1">^1</xliff:g> toe om <xliff:g id="COUNT">^2</xliff:g> video\'s te wysig?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Veiligheidbeskerming"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Toestelspesifieke kodewisselingopletberigte"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Toestelspesifieke kodewisselingvordering"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Sommige foto’s kan nie laai nie"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Het dit"</string> </resources> diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index 44e9b1c77..b5c3edccd 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"ማህደረመረጃ"</string> <string name="storage_description" msgid="4081716890357580107">"አካባቢያዊ ማከማቻ"</string> <string name="app_label" msgid="9035307001052716210">"ማህደረ መረጃ ማከማቻ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"ሚዲያ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"የሚዲያ መራጭ"</string> <string name="artist_label" msgid="8105600993099120273">"አርቲስት"</string> <string name="unknown" msgid="2059049215682829375">"የማይታወቅ"</string> <string name="root_images" msgid="5861633549189045666">"ምስሎች"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"የደመና ሚዲያን ይድረሱ ከ"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ምንም"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"በዚህ ጊዜ የደመና የሚዲያ መተግበሪያን መለወጥ አልተቻለም።"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"የሚዲያ መራጭ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"የሚዲያ መራጭ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"ሚዲያ በማስመር ላይ…"</string> <string name="add" msgid="2894574044585549298">"አክል"</string> <string name="deselect" msgid="4297825044827769490">"አትምረጥ"</string> <string name="deselected" msgid="8488133193326208475">"አልተመረጠም"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"የበይነመረብዎን ግንኙነት ይፈትሹ እና እንደገና ይሞክሩ"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"እንደገና ሞክር"</string> <string name="not_selected" msgid="2244008151669896758">"አልተመረጠም"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"የእርስዎን የተመረጠ ሚዲያ በማዘጋጀት ላይ"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> ከ<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ዝግጁ"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ምትኬ የተቀመጠላቸው ፎቶዎች አሁን ተካትተዋል"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"ከ<xliff:g id="APP_NAME">%1$s</xliff:g> መለያ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> ፎቶዎችን መምረጥ ይችላሉ"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"መተግበሪያ ይምረጡ"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"መለያ ይምረጡ"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"መለያ ቀይር"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"ሁሉንም ፎቶዎችዎን በማምጣት ላይ"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ይህን ኦዲዮ ፋይል እንዲቀይር ይፈቀድለት?}one{<xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> ኦዲዮ ፋይልን እንዲቀይር ይፈቀድለት?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> ኦዲዮ ፋይሎችን እንዲቀይር ይፈቀድለት?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{የኦዲዮ ፋይልን በመቀየር ላይ…}one{<xliff:g id="COUNT">^1</xliff:g> የኦዲዮ ፋይልን በመቀየር ላይ…}other{<xliff:g id="COUNT">^1</xliff:g> የኦዲዮ ፋይሎችን በመቀየር ላይ…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ይህን ቪዲዮ እንዲቀይር ይፈቀድለት?}one{<xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> ቪዲዮን እንዲቀይር ይፈቀድለት?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> ቪዲዮዎችን እንዲቀይር ይፈቀድለት?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"የደህንነት ጥበቃ"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"የቤተኛ ትራንስኮድ ማንቂያዎች"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"የቤተኛ ትራንስኮድ ሂደት"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"አንዳንድ ፎቶዎችን መጫን አይቻለም"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ገባኝ"</string> </resources> diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index c8544f1e6..de14d5650 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"الوسائط"</string> <string name="storage_description" msgid="4081716890357580107">"التخزين المحلي"</string> <string name="app_label" msgid="9035307001052716210">"تخزين الوسائط"</string> - <string name="picker_app_label" msgid="4254039089502164761">"الوسائط"</string> + <string name="picker_app_label" msgid="1195424381053599122">"أداة اختيار الوسائط"</string> <string name="artist_label" msgid="8105600993099120273">"الفنان"</string> <string name="unknown" msgid="2059049215682829375">"غير معروف"</string> <string name="root_images" msgid="5861633549189045666">"الصور"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"الوصول إلى الوسائط في السحابة الإلكترونية من"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"بلا تطبيق"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"تعذر تغيير تطبيق وسائط في السحابة الإلكترونية حاليًا"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"أداة اختيار الوسائط"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"أداة اختيار الوسائط"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"جارٍ مزامنة الوسائط…"</string> <string name="add" msgid="2894574044585549298">"إضافة"</string> <string name="deselect" msgid="4297825044827769490">"إلغاء الاختيار"</string> <string name="deselected" msgid="8488133193326208475">"تم إلغاء الاختيار"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"يُرجى التحقّق من الاتصال بالإنترنت ثم إعادة المحاولة."</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"إعادة المحاولة"</string> <string name="not_selected" msgid="2244008151669896758">"غير محدّد"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"جارٍ تحضير الوسائط التي تم اختيارها"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> من إجمالي <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> صورة جاهزة"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"تم الآن تضمين الصور التي تم الاحتفاظ بنسخة احتياطية منها"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"يمكنك اختيار صور من حساب <xliff:g id="APP_NAME">%1$s</xliff:g> للمستخدم <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>."</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"يمكنك اختيار صور من حساب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" للمستخدم <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>."</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"تم تعديل الحساب <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"تم الآن تضمين الصور من <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> هنا."</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"اختيار تطبيق موسيقى على السحابة الإلكترونية"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"اختيار تطبيق"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"اختيار حساب"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"تبديل الحساب"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"جارٍ تحميل جميع الصور"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_0">^1</xliff:g> بتعديل هذا الملف الصوتي؟}zero{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> ملف صوتي؟}two{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل ملفَين صوتيين (<xliff:g id="COUNT">^2</xliff:g>)؟}few{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> ملفات صوتية؟}many{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> ملفًا صوتيًا؟}other{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> ملف صوتي؟}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{جارٍ تعديل ملف صوتي واحد…}zero{جارٍ تعديل <xliff:g id="COUNT">^1</xliff:g> ملف صوتي…}two{جارٍ تعديل ملفَين صوتين (<xliff:g id="COUNT">^1</xliff:g>)…}few{جارٍ تعديل <xliff:g id="COUNT">^1</xliff:g> ملفات صوتية…}many{جارٍ تعديل <xliff:g id="COUNT">^1</xliff:g> ملفًا صوتيًا…}other{جارٍ تعديل <xliff:g id="COUNT">^1</xliff:g> ملف صوتي…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_0">^1</xliff:g> بتعديل هذا الفيديو؟}zero{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> فيديو؟}two{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل فيديوهين (<xliff:g id="COUNT">^2</xliff:g>)؟}few{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> فيديوهات؟}many{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> فيديو؟}other{هل تريد السماح لتطبيق <xliff:g id="APP_NAME_1">^1</xliff:g> بتعديل <xliff:g id="COUNT">^2</xliff:g> فيديو؟}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"حماية الأمن الشخصي"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"تنبيهات Native Transcode"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"مدى تقدُّم Native Transcode"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"يتعذّر تحميل بعض الصور"</string> + <string name="dialog_button_text" msgid="351366485240852280">"حسنًا"</string> </resources> diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index 25f559634..db0cd53fb 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"মিডিয়া"</string> <string name="storage_description" msgid="4081716890357580107">"স্থানীয় ষ্ট’ৰেজ"</string> <string name="app_label" msgid="9035307001052716210">"মিডিয়া ষ্ট’ৰেজ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"মিডিয়া"</string> + <string name="picker_app_label" msgid="1195424381053599122">"মিডিয়া বাছনিকৰ্তা"</string> <string name="artist_label" msgid="8105600993099120273">"শিল্পী"</string> <string name="unknown" msgid="2059049215682829375">"অজ্ঞাত"</string> <string name="root_images" msgid="5861633549189045666">"প্ৰতিচ্ছবি"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ইয়াৰ পৰা ক্লাউড মিডিয়া এক্সেছ কৰক"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"নাই"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"এই সময়ত ক্লাউড মিডিয়া এপ্ সলনি কৰিব নোৱাৰি"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"মিডিয়া বাছনিকৰ্তা"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"মিডিয়া বাছনিকৰ্তা"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"মিডিয়া ছিংক কৰি থকা হৈছে…"</string> <string name="add" msgid="2894574044585549298">"যোগ দিয়ক"</string> <string name="deselect" msgid="4297825044827769490">"বাছনিৰ পৰা আঁতৰাওক"</string> <string name="deselected" msgid="8488133193326208475">"বাছনিৰ পৰা আঁতৰোৱা হ’ল"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"আপোনাৰ ইণ্টাৰনেট সংযোগ পৰীক্ষা কৰক আৰু পুনৰ চেষ্টা কৰক"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"পুনৰ চেষ্টা কৰক"</string> <string name="not_selected" msgid="2244008151669896758">"বাছনি কৰা হোৱা নাই"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"আপুনি বাছনি কৰা মিডিয়া সাজু কৰি থকা হৈছে"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> টা বস্তুৰ ভিতৰত <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> টা সাজু"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"এতিয়া বেকআপ লোৱা ফট’সমূহ অন্তৰ্ভুক্ত কৰা হৈছে"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"আপুনি <xliff:g id="APP_NAME">%1$s</xliff:g>ৰ একাউণ্টৰ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> পৰা ফট’সমূহ বাছনি কৰিব পাৰে"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"এপ্ বাছনি কৰক"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"একাউণ্ট বাছনি কৰক"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"একাউণ্ট সলনি কৰক"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"আপোনাৰ আটাইবোৰ ফট’ পাই থকা হৈছে"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>ক এই অডিঅ’ ফাইলটো সংশোধন কৰিবলৈ অনুমতি দিবনে?}one{<xliff:g id="APP_NAME_1">^1</xliff:g>ক <xliff:g id="COUNT">^2</xliff:g> টা অডিঅ’ ফাইল সংশোধন কৰিবলৈ অনুমতি দিবনে?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>ক <xliff:g id="COUNT">^2</xliff:g> টা অডিঅ’ ফাইল সংশোধন কৰিবলৈ অনুমতি দিবনে?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{অডিঅ’ ফাইলটো সংশোধন কৰি থকা হৈছে…}one{<xliff:g id="COUNT">^1</xliff:g> টা অডিঅ’ ফাইল সংশোধন কৰি থকা হৈছে…}other{<xliff:g id="COUNT">^1</xliff:g> টা অডিঅ’ ফাইল সংশোধন কৰি থকা হৈছে…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>ক এই ভিডিঅ’টো সংশোধন কৰিবলৈ অনুমতি দিবনে?}one{<xliff:g id="APP_NAME_1">^1</xliff:g>ক <xliff:g id="COUNT">^2</xliff:g> টা ভিডিঅ’ সংশোধন কৰিবলৈ অনুমতি দিবনে?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>ক <xliff:g id="COUNT">^2</xliff:g> টা ভিডিঅ’ সংশোধন কৰিবলৈ অনুমতি দিবনে?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"সুৰক্ষিত নিৰাপত্তা"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"স্থানীয় ট্ৰেন্সক’ড সতৰ্কবাৰ্তা"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"স্থানীয় ট্ৰেন্সক’ড অগ্ৰগতি"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"কিছুমান ফট’ ল’ড কৰিব নোৱাৰি"</string> + <string name="dialog_button_text" msgid="351366485240852280">"বুজি পালোঁ"</string> </resources> diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index ff42afe61..9fa2b25d3 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Yerli yaddaş"</string> <string name="app_label" msgid="9035307001052716210">"Media Yaddaşı"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Media seçici"</string> <string name="artist_label" msgid="8105600993099120273">"Sənətçi"</string> <string name="unknown" msgid="2059049215682829375">"Naməlum"</string> <string name="root_images" msgid="5861633549189045666">"Təsvirlər"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Bulud mediasına buradan giriş edin:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Heç biri"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"İndi bulud media tətbiqini dəyişmək mümkün deyil."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Media seçici"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Media seçici"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Media sinxronlaşdırılır…"</string> <string name="add" msgid="2894574044585549298">"Əlavə edin"</string> <string name="deselect" msgid="4297825044827769490">"Seçimi ləğv edin"</string> <string name="deselected" msgid="8488133193326208475">"Seçimi ləğv edilib"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"İnternet bağlantınızı yoxlayın və yenidən sınayın"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Yenidən cəhd edin"</string> <string name="not_selected" msgid="2244008151669896758">"seçilməyib"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Seçilmiş media hazırlanır"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>/<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> hazırdır"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Yedəklənmiş fotolar indi daxildir"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> hesabından (<xliff:g id="USER_ACCOUNT">%2$s</xliff:g>) fotoları seçə bilərsiniz"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Tətbiq seçin"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Hesab seçin"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Hesabı dəyişdirin"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Bütün fotolar əldə edilir"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> tətbiqinə bu audio fayla dəyişiklik etmək icazəsi verilsin?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> tətbiqinə <xliff:g id="COUNT">^2</xliff:g> audio fayla dəyişiklik etmək icazəsi verilsin?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Audio fayl dəyişdirilir…}other{<xliff:g id="COUNT">^1</xliff:g> audio fayl dəyişdirilir…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> tətbiqinə bu videoya dəyişiklik etmək icazəsi verilsin?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> tətbiqinə <xliff:g id="COUNT">^2</xliff:g> videoya dəyişiklik etmək icazəsi verilsin?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Güvənlik qoruması"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Orijinal Transkod Xəbərdarlıqları"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Orijinal Transkod İrəliləyişi"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Bəzi fotolar yüklənmir"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Anladım"</string> </resources> diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index cc2d31d13..3d759fa64 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Mediji"</string> <string name="storage_description" msgid="4081716890357580107">"Lokalni memorijski prostor"</string> <string name="app_label" msgid="9035307001052716210">"Memorijski prostor za medije"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Mediji"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Birač medija"</string> <string name="artist_label" msgid="8105600993099120273">"Izvođač"</string> <string name="unknown" msgid="2059049215682829375">"Nepoznato"</string> <string name="root_images" msgid="5861633549189045666">"Slike"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Pristupajte medijima u klaudu iz"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ništa"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Promena aplikacije za medije u klaudu nije uspela."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Birač medija"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Birač medija"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Mediji se sinhronizuju…"</string> <string name="add" msgid="2894574044585549298">"Dodaj"</string> <string name="deselect" msgid="4297825044827769490">"Opozovi izbor"</string> <string name="deselected" msgid="8488133193326208475">"Opozvan je izbor"</string> @@ -53,8 +56,8 @@ <string name="selected" msgid="9151797369975828124">"Izabrano"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{Izaberite najviše <xliff:g id="COUNT_0">^1</xliff:g> stavku}one{Izaberite najviše <xliff:g id="COUNT_1">^1</xliff:g> stavku}few{Izaberite najviše <xliff:g id="COUNT_1">^1</xliff:g> stavke}other{Izaberite najviše <xliff:g id="COUNT_1">^1</xliff:g> stavki}}"</string> <string name="recent" msgid="6694613584743207874">"Nedavno"</string> - <string name="picker_photos_empty_message" msgid="5980619500554575558">"Nema slika niti video snimaka"</string> - <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Nema podržanih slika niti video snimaka"</string> + <string name="picker_photos_empty_message" msgid="5980619500554575558">"Nema slika niti videa"</string> + <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Nema podržanih slika niti videa"</string> <string name="picker_albums_empty_message" msgid="8341079772950966815">"Nema albuma"</string> <string name="picker_view_selected" msgid="2266031384396143883">"Prikaži izabrano"</string> <string name="picker_photos" msgid="7415035516411087392">"Slike"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Proverite internet vezu i probajte ponovo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Probaj ponovo"</string> <string name="not_selected" msgid="2244008151669896758">"nije izabrano"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Pripremaju se odabrani medijski fajlovi"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Spremno:<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> od <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Sada su uvrštene rezervne kopije slika"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Možete da izaberete slike sa naloga <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> za <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,34 +110,35 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Odaberi aplikaciju"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Odaberi nalog"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Promeni nalog"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Preuzimaju se sve slike"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izmeni ovaj audio fajl?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> audio fajl?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> audio fajla?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> audio fajlova?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Menja se audio fajl…}one{Menja se <xliff:g id="COUNT">^1</xliff:g> audio fajl…}few{Menjaju se <xliff:g id="COUNT">^1</xliff:g> audio fajla…}other{Menja se <xliff:g id="COUNT">^1</xliff:g> audio fajlova…}}"</string> - <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izmeni ovaj video?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> video?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> video snimka?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> video snimaka?}}"</string> - <string name="permission_progress_write_video" msgid="7014908418349819148">"{count,plural, =1{Menja se video…}one{Menja se <xliff:g id="COUNT">^1</xliff:g> video…}few{Menjaju se <xliff:g id="COUNT">^1</xliff:g> video snimka…}other{Menja se <xliff:g id="COUNT">^1</xliff:g> video snimaka…}}"</string> + <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izmeni ovaj video?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> video?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> video snimka?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> videa?}}"</string> + <string name="permission_progress_write_video" msgid="7014908418349819148">"{count,plural, =1{Menja se video…}one{Menja se <xliff:g id="COUNT">^1</xliff:g> video…}few{Menjaju se <xliff:g id="COUNT">^1</xliff:g> video snimka…}other{Menja se <xliff:g id="COUNT">^1</xliff:g> videa…}}"</string> <string name="permission_write_image" msgid="3518991791620523786">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izmeni ovu sliku?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> sliku?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> slike?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> slika?}}"</string> <string name="permission_progress_write_image" msgid="3623580315590025262">"{count,plural, =1{Menja se slika…}one{Menja se <xliff:g id="COUNT">^1</xliff:g> slika…}few{Menjaju se <xliff:g id="COUNT">^1</xliff:g> slike…}other{Menja se <xliff:g id="COUNT">^1</xliff:g> slika…}}"</string> <string name="permission_write_generic" msgid="7431128739233656991">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izmeni ovu stavku?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> stavku?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> stavke?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izmeni <xliff:g id="COUNT">^2</xliff:g> stavki?}}"</string> <string name="permission_progress_write_generic" msgid="2806560971318391443">"{count,plural, =1{Menja se stavka…}one{Menja se <xliff:g id="COUNT">^1</xliff:g> stavka…}few{Menjaju se <xliff:g id="COUNT">^1</xliff:g> stavke…}other{Menja se <xliff:g id="COUNT">^1</xliff:g> stavki…}}"</string> <string name="permission_trash_audio" msgid="6554672354767742206">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovaj audio fajl u otpad?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> audio fajl u otpad?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> audio fajla u otpad?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> audio fajlova u otpad?}}"</string> <string name="permission_progress_trash_audio" msgid="3116279868733641329">"{count,plural, =1{Audio fajl se premešta u otpad…}one{<xliff:g id="COUNT">^1</xliff:g> audio fajl se premešta u otpad…}few{<xliff:g id="COUNT">^1</xliff:g> audio fajla se premeštaju u otpad…}other{<xliff:g id="COUNT">^1</xliff:g> audio fajlova se premešta u otpad…}}"</string> - <string name="permission_trash_video" msgid="7555850843259959642">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovaj video u otpad?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video u otpad?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video snimka u otpad?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video snimaka u otpad?}}"</string> - <string name="permission_progress_trash_video" msgid="4637821778329459681">"{count,plural, =1{Video se premešta u otpad…}one{<xliff:g id="COUNT">^1</xliff:g> video se premešta u otpad…}few{<xliff:g id="COUNT">^1</xliff:g> video snimka se premeštaju u otpad…}other{<xliff:g id="COUNT">^1</xliff:g> video snimaka se premešta u otpad…}}"</string> + <string name="permission_trash_video" msgid="7555850843259959642">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovaj video u otpad?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video u otpad?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video snimka u otpad?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> videa u otpad?}}"</string> + <string name="permission_progress_trash_video" msgid="4637821778329459681">"{count,plural, =1{Video se premešta u otpad…}one{<xliff:g id="COUNT">^1</xliff:g> video se premešta u otpad…}few{<xliff:g id="COUNT">^1</xliff:g> video snimka se premeštaju u otpad…}other{<xliff:g id="COUNT">^1</xliff:g> videa se premešta u otpad…}}"</string> <string name="permission_trash_image" msgid="3333128084684156675">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovu sliku u otpad?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> sliku u otpad?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> slike u otpad?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> slika u otpad?}}"</string> <string name="permission_progress_trash_image" msgid="3063857679090024764">"{count,plural, =1{Slika se premešta u otpad…}one{<xliff:g id="COUNT">^1</xliff:g> slika se premešta u otpad…}few{<xliff:g id="COUNT">^1</xliff:g> slike se premeštaju u otpad…}other{<xliff:g id="COUNT">^1</xliff:g> slika se premešta u otpad…}}"</string> <string name="permission_trash_generic" msgid="5545420534785075362">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovu stavku u otpad?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> stavku u otpad?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> stavke u otpad?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> stavki u otpad?}}"</string> <string name="permission_progress_trash_generic" msgid="7815124979717814057">"{count,plural, =1{Stavka se premešta u otpad…}one{<xliff:g id="COUNT">^1</xliff:g> stavka se premešta u otpad…}few{<xliff:g id="COUNT">^1</xliff:g> stavke se premeštaju u otpad…}other{<xliff:g id="COUNT">^1</xliff:g> stavki se premešta u otpad…}}"</string> <string name="permission_untrash_audio" msgid="8404597563284002472">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovaj audio fajl iz otpada?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> audio fajl iz otpada?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> audio fajla iz otpada?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> audio fajlova iz otpada?}}"</string> <string name="permission_progress_untrash_audio" msgid="2775372344946464508">"{count,plural, =1{Audio fajl se premešta iz otpada…}one{<xliff:g id="COUNT">^1</xliff:g> audio fajl se premešta iz otpada…}few{<xliff:g id="COUNT">^1</xliff:g> audio fajla se premeštaju iz otpada…}other{<xliff:g id="COUNT">^1</xliff:g> audio fajlova se premešta iz otpada…}}"</string> - <string name="permission_untrash_video" msgid="3178914827607608162">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovaj video iz otpada?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video iz otpada?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video snimka iz otpada?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video snimaka iz otpada?}}"</string> - <string name="permission_progress_untrash_video" msgid="5500929409733841567">"{count,plural, =1{Video se premešta iz otpada…}one{<xliff:g id="COUNT">^1</xliff:g> video se premešta iz otpada…}few{<xliff:g id="COUNT">^1</xliff:g> video snimka se premeštaju iz otpada…}other{<xliff:g id="COUNT">^1</xliff:g> video snimaka se premešta iz otpada…}}"</string> + <string name="permission_untrash_video" msgid="3178914827607608162">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovaj video iz otpada?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video iz otpada?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> video snimka iz otpada?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> videa iz otpada?}}"</string> + <string name="permission_progress_untrash_video" msgid="5500929409733841567">"{count,plural, =1{Video se premešta iz otpada…}one{<xliff:g id="COUNT">^1</xliff:g> video se premešta iz otpada…}few{<xliff:g id="COUNT">^1</xliff:g> video snimka se premeštaju iz otpada…}other{<xliff:g id="COUNT">^1</xliff:g> videa se premešta iz otpada…}}"</string> <string name="permission_untrash_image" msgid="3397523279351032265">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovu sliku iz otpada?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> sliku iz otpada?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> slike iz otpada?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> slika iz otpada?}}"</string> <string name="permission_progress_untrash_image" msgid="5295061520504846264">"{count,plural, =1{Slika se premešta iz otpada…}one{<xliff:g id="COUNT">^1</xliff:g> slika se premešta iz otpada…}few{<xliff:g id="COUNT">^1</xliff:g> slike se premeštaju iz otpada…}other{<xliff:g id="COUNT">^1</xliff:g> slika se premešta iz otpada…}}"</string> <string name="permission_untrash_generic" msgid="2118366929431671046">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> premesti ovu stavku iz otpada?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> stavku iz otpada?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> stavke iz otpada?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> premesti <xliff:g id="COUNT">^2</xliff:g> stavki iz otpada?}}"</string> <string name="permission_progress_untrash_generic" msgid="1489511601966842579">"{count,plural, =1{Stavka se premešta iz otpada…}one{<xliff:g id="COUNT">^1</xliff:g> stavka se premešta iz otpada…}few{<xliff:g id="COUNT">^1</xliff:g> stavke se premeštaju iz otpada…}other{<xliff:g id="COUNT">^1</xliff:g> stavki se premešta iz otpada…}}"</string> <string name="permission_delete_audio" msgid="3326674742892796627">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izbriše ovaj audio fajl?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> audio fajl?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> audio fajla?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> audio fajlova?}}"</string> <string name="permission_progress_delete_audio" msgid="1734871539021696401">"{count,plural, =1{Briše se audio fajl…}one{Briše se <xliff:g id="COUNT">^1</xliff:g> audio fajl…}few{Brišu se <xliff:g id="COUNT">^1</xliff:g> audio fajla…}other{Briše se <xliff:g id="COUNT">^1</xliff:g> audio fajlova…}}"</string> - <string name="permission_delete_video" msgid="604024971828349279">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izbriše ovaj video?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> video?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> video snimka?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> video snimaka?}}"</string> - <string name="permission_progress_delete_video" msgid="1846702435073793157">"{count,plural, =1{Briše se video…}one{Briše se <xliff:g id="COUNT">^1</xliff:g> video…}few{Brišu se <xliff:g id="COUNT">^1</xliff:g> video snimka…}other{Briše se <xliff:g id="COUNT">^1</xliff:g> video snimaka…}}"</string> + <string name="permission_delete_video" msgid="604024971828349279">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izbriše ovaj video?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> video?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> video snimka?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> videa?}}"</string> + <string name="permission_progress_delete_video" msgid="1846702435073793157">"{count,plural, =1{Briše se video…}one{Briše se <xliff:g id="COUNT">^1</xliff:g> video…}few{Brišu se <xliff:g id="COUNT">^1</xliff:g> video snimka…}other{Briše se <xliff:g id="COUNT">^1</xliff:g> videa…}}"</string> <string name="permission_delete_image" msgid="3109056012794330510">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izbriše ovu sliku?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> sliku?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> slike?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> slika?}}"</string> <string name="permission_progress_delete_image" msgid="8580517204901148906">"{count,plural, =1{Briše se slika…}one{Briše se <xliff:g id="COUNT">^1</xliff:g> slika…}few{Brišu se <xliff:g id="COUNT">^1</xliff:g> slike…}other{Briše se <xliff:g id="COUNT">^1</xliff:g> slika…}}"</string> <string name="permission_delete_generic" msgid="7891939881065520271">"{count,plural, =1{Želite li da dozvolite da <xliff:g id="APP_NAME_0">^1</xliff:g> izbriše ovu stavku?}one{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> stavku?}few{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> stavke?}other{Želite li da dozvolite da <xliff:g id="APP_NAME_1">^1</xliff:g> izbriše <xliff:g id="COUNT">^2</xliff:g> stavki?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Sigurnosna zaštita"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Obaveštenja o osnovnom transkodiranju"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Tok osnovnog transkodiranja"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Učitavanje nekih slika nije uspelo"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Važi"</string> </resources> diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index f7f5b9713..1b71e81a3 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Медыя"</string> <string name="storage_description" msgid="4081716890357580107">"Лакальнае сховішча"</string> <string name="app_label" msgid="9035307001052716210">"Медыясховішча"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Мультымедыя"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Сродак выбару мультымедыя"</string> <string name="artist_label" msgid="8105600993099120273">"Выканаўца"</string> <string name="unknown" msgid="2059049215682829375">"Невядома"</string> <string name="root_images" msgid="5861633549189045666">"Відарысы"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Доступ да воблачных мультымедыя з:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Няма"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Воблачныя мультымедыйныя праграмы не зменены."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Сродак выбару мультымедыя"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Сродак выбару мультымедыя"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Ідзе сінхранізацыя мультымедыя…"</string> <string name="add" msgid="2894574044585549298">"Дадаць"</string> <string name="deselect" msgid="4297825044827769490">"Адмяніць выбар"</string> <string name="deselected" msgid="8488133193326208475">"Выбар скасаваны"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Праверце падключэнне да інтэрнэту і паўтарыце спробу"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Паўтарыць спробу"</string> <string name="not_selected" msgid="2244008151669896758">"не выбраны"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Ідзе падрыхтоўка выбраных вамі медыяфайлаў"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Гатова: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> з <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Цяпер дададзены рэзервовыя копіі фотаздымкаў"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Вы можаце выбраць фотаздымкі з уліковага запісу <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Выбраць праграму"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Выбраць уліковы запіс"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Змяніць уліковы запіс"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Вашы фота загружаюцца"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Дазволіць праграме \"<xliff:g id="APP_NAME_0">^1</xliff:g>\" змяніць гэты аўдыяфайл?}one{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> аўдыяфайл?}few{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> аўдыяфайлы?}many{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> аўдыяфайлаў?}other{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> аўдыяфайла?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Змяняецца аўдыяфайл…}one{Змяняецца <xliff:g id="COUNT">^1</xliff:g> аўдыяфайл…}few{Змяняюцца <xliff:g id="COUNT">^1</xliff:g> аўдыяфайлы…}many{Змяняюцца <xliff:g id="COUNT">^1</xliff:g> аўдыяфайлаў…}other{Змяняюцца <xliff:g id="COUNT">^1</xliff:g> аўдыяфайла…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Дазволіць праграме \"<xliff:g id="APP_NAME_0">^1</xliff:g>\" змяніць гэта відэа?}one{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> відэа?}few{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> відэа?}many{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> відэа?}other{Дазволіць праграме \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" змяніць <xliff:g id="COUNT">^2</xliff:g> відэа?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Ахова бяспекі"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Абвесткі пра ўбудаванае перакадзіраванне"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Ход убудаванага перакадзіравання"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Некаторыя фота не ўдалося загрузіць"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index dbd02206a..adb514e72 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Мултимедия"</string> <string name="storage_description" msgid="4081716890357580107">"Локално хранилище"</string> <string name="app_label" msgid="9035307001052716210">"Мултимедийно хранилище"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Мултимедия"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Инструмент за избор на носители"</string> <string name="artist_label" msgid="8105600993099120273">"Изпълнител"</string> <string name="unknown" msgid="2059049215682829375">"Неизвестно"</string> <string name="root_images" msgid="5861633549189045666">"Изображения"</string> @@ -39,16 +39,19 @@ <string name="allow" msgid="8885707816848569619">"Разрешаване"</string> <string name="deny" msgid="6040983710442068936">"Отказ"</string> <string name="picker_browse" msgid="5554477454636075934">"Преглед…"</string> - <string name="picker_settings" msgid="6443463167344790260">"Медийно приложение в облака"</string> + <string name="picker_settings" msgid="6443463167344790260">"Прил. за мултимедия в облака"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Приложение за мултимедия в облака"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Приложение за мултимедия в облака"</string> <string name="picker_settings_description" msgid="2916686824777214585">"Осъществяване на достъп до мултимедията в облака, когато приложение или уебсайт иска от вас да изберете снимки или видеоклипове"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Достъп до мултимедия в облака от"</string> - <string name="picker_settings_no_provider" msgid="2582311853680058223">"Няма"</string> + <string name="picker_settings_no_provider" msgid="2582311853680058223">"Нищо"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Медийното приложение в облака не бе променено."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Инструмент за избор на мултимедия"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Инструмент за избор на мултимедия"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Мултимедията се синхронизира…"</string> <string name="add" msgid="2894574044585549298">"Добавяне"</string> <string name="deselect" msgid="4297825044827769490">"Премахване на избора"</string> - <string name="deselected" msgid="8488133193326208475">"Неизбрано"</string> + <string name="deselected" msgid="8488133193326208475">"Отменен избор"</string> <string name="select" msgid="2704765470563027689">"Избиране"</string> <string name="selected" msgid="9151797369975828124">"Избрано"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{Изберете най-много <xliff:g id="COUNT_0">^1</xliff:g> елемент}other{Изберете най-много <xliff:g id="COUNT_1">^1</xliff:g> елемента}}"</string> @@ -61,7 +64,7 @@ <string name="picker_albums" msgid="4822511902115299142">"Албуми"</string> <string name="picker_preview" msgid="6257414886055861039">"Визуализация"</string> <string name="picker_work_profile" msgid="2083221066869141576">"Превкл. към служ. пoтр. профил"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Превключване към личния потребителски профил"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Превкл. към личния потр. профил"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Блокирано от администратора ви"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Достъпът до служебни данни от лично приложение не е разрешен"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Достъпът до лични данни от служебно приложение не е разрешен"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Проверете връзката си с интернет и опитайте отново"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Нов опит"</string> <string name="not_selected" msgid="2244008151669896758">"не е избрано"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Избраната от вас мултимедия се подготвя"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Готови: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> от <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Снимките, за които е създадено резервно копие, вече са добавени"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Можете да избирате снимки от профила <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> в(ъв) <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Избиране на приложение"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Избиране на профил"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Промяна на профила"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Всичките ви снимки се извличат"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Да се разреши ли на <xliff:g id="APP_NAME_0">^1</xliff:g> да промени този аудиофайл?}other{Да се разреши ли на <xliff:g id="APP_NAME_1">^1</xliff:g> да промени <xliff:g id="COUNT">^2</xliff:g> аудиофайла?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Аудиофайлът се променя…}other{<xliff:g id="COUNT">^1</xliff:g> аудиофайла се променят…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Да се разреши ли на <xliff:g id="APP_NAME_0">^1</xliff:g> да промени този видеоклип?}other{Да се разреши ли на <xliff:g id="APP_NAME_1">^1</xliff:g> да промени <xliff:g id="COUNT">^2</xliff:g> видеоклипа?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Защита на безопасността"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Стандартни сигнали за прекодиране"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Стандартен прогрес при прекодиране"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Някои снимки не могат да се заредят"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Разбрах"</string> </resources> diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index 4ce4bee8a..e0ccfb3c7 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"মিডিয়া"</string> <string name="storage_description" msgid="4081716890357580107">"স্থানীয় স্টোরেজ"</string> <string name="app_label" msgid="9035307001052716210">"মিডিয়া স্টোরেজ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"মিডিয়া"</string> + <string name="picker_app_label" msgid="1195424381053599122">"মিডিয়া বাছাইকারি"</string> <string name="artist_label" msgid="8105600993099120273">"শিল্পী"</string> <string name="unknown" msgid="2059049215682829375">"অজানা"</string> <string name="root_images" msgid="5861633549189045666">"ছবি"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"এখান থেকে ক্লাউড মিডিয়া অ্যাক্সেস করুন"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"কোনওটিই নয়"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"এই মুহূর্তে ক্লাউড মিডিয়া অ্যাপ বদল করা যায়নি।"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"মিডিয়া বাছাইকারী"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"মিডিয়া বাছাইকারী"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"মিডিয়া সিঙ্ক করছে…"</string> <string name="add" msgid="2894574044585549298">"যোগ করুন"</string> <string name="deselect" msgid="4297825044827769490">"টিক চিহ্নটি সরিয়ে দিন"</string> <string name="deselected" msgid="8488133193326208475">"টিকচিহ্ন সরিয়ে দিন"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ইন্টারনেট কানেকশন ঠিক আছে কিনা দেখে নিয়ে আবার চেষ্টা করুন"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"আবার চেষ্টা করুন"</string> <string name="not_selected" msgid="2244008151669896758">"বেছে নেওয়া হয়নি"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"আপনার বেছে নেওয়া মিডিয়া রেডি করা হচ্ছে"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> নম্বর আইটেম রেডি আছে"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ব্যাক-আপ নেওয়া ফটো এখন যোগ করা হয়েছে"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"আপনি <xliff:g id="APP_NAME">%1$s</xliff:g>-এর অ্যাকাউন্ট <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> থেকে ফটো বেছে নিতে পারবেন"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"অ্যাপ বেছে নিন"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"অ্যাকাউন্ট বেছে নিন"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"অ্যাকাউন্ট পরিবর্তন করুন"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"আপনার সব ফটো লোড করা হচ্ছে"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>-কে এই অডিও ফাইল পরিবর্তন করার অনুমতি দিতে চান?}one{<xliff:g id="APP_NAME_1">^1</xliff:g>-কে <xliff:g id="COUNT">^2</xliff:g>টি অডিও ফাইল পরিবর্তন করার অনুমতি দিতে চান?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>-কে <xliff:g id="COUNT">^2</xliff:g>টি অডিও ফাইল পরিবর্তন করার অনুমতি দিতে চান?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{অডিও ফাইলে পরিবর্তন করা হচ্ছে…}one{<xliff:g id="COUNT">^1</xliff:g>টি অডিও ফাইলে পরিবর্তন করা হচ্ছে…}other{<xliff:g id="COUNT">^1</xliff:g>টি অডিও ফাইলে পরিবর্তন করা হচ্ছে…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>-কে এই ভিডিও পরিবর্তন করার অনুমতি দিতে চান?}one{<xliff:g id="APP_NAME_1">^1</xliff:g>-কে <xliff:g id="COUNT">^2</xliff:g>টি ভিডিও পরিবর্তন করার অনুমতি দিতে চান?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>-কে <xliff:g id="COUNT">^2</xliff:g>টি ভিডিও পরিবর্তন করার অনুমতি দিতে চান?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"নিরাপত্তার সুরক্ষা"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"নেটিভ ট্রান্সকোড অ্যালার্ট"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"নেটিভ ট্রান্সকোড প্রোগ্রেস"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"কিছু ফটো লোড করা যাচ্ছে না"</string> + <string name="dialog_button_text" msgid="351366485240852280">"বুঝেছি"</string> </resources> diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 99bd07ce2..d701edd1f 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Mediji"</string> <string name="storage_description" msgid="4081716890357580107">"Lokalna pohrana"</string> <string name="app_label" msgid="9035307001052716210">"Medijska pohrana"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Medij"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Izbornik medijskog sadržaja"</string> <string name="artist_label" msgid="8105600993099120273">"Umjetnik"</string> <string name="unknown" msgid="2059049215682829375">"Nepoznato"</string> <string name="root_images" msgid="5861633549189045666">"Slike"</string> @@ -39,16 +39,19 @@ <string name="allow" msgid="8885707816848569619">"Dozvoli"</string> <string name="deny" msgid="6040983710442068936">"Odbij"</string> <string name="picker_browse" msgid="5554477454636075934">"Pregledajte…"</string> - <string name="picker_settings" msgid="6443463167344790260">"Apl. za med. sadržaje u oblaku"</string> - <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Aplikacija za medijske sadržaje u oblaku"</string> + <string name="picker_settings" msgid="6443463167344790260">"Aplikacija za medije u oblaku"</string> + <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Aplikacija za medije u oblaku"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Aplikacija za medijske sadržaje u oblaku"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Pristupite medijima na oblaku kada vam aplikacija ili web lokacija zatraži da odaberete fotografije ili videozapise"</string> - <string name="picker_settings_selection_message" msgid="245453573086488596">"Pristupite medijskom sadržaju u oblaku iz"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Pristupite medijima u oblaku kada vam aplikacija ili web lokacija zatraži da odaberete fotografije ili videozapise"</string> + <string name="picker_settings_selection_message" msgid="245453573086488596">"Pristupite medijima u oblaku iz oblaku iz"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ništa"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Promjena medijske aplikacije u oblaku nije uspjela."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Izbornik medijskog sadržaja"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Izbornik medijskog sadržaja"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sinhroniziranje medijskog sadržaja…"</string> <string name="add" msgid="2894574044585549298">"Dodaj"</string> <string name="deselect" msgid="4297825044827769490">"Poništi odabir"</string> - <string name="deselected" msgid="8488133193326208475">"Odabir poništen"</string> + <string name="deselected" msgid="8488133193326208475">"Odabir je poništen"</string> <string name="select" msgid="2704765470563027689">"Odaberi"</string> <string name="selected" msgid="9151797369975828124">"Odabrano"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{Odaberite najviše <xliff:g id="COUNT_0">^1</xliff:g> stavku}one{Odaberite najviše <xliff:g id="COUNT_1">^1</xliff:g> stavku}few{Odaberite najviše <xliff:g id="COUNT_1">^1</xliff:g> stavke}other{Odaberite najviše <xliff:g id="COUNT_1">^1</xliff:g> stavki}}"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Fotografije"</string> <string name="picker_albums" msgid="4822511902115299142">"Albumi"</string> <string name="picker_preview" msgid="6257414886055861039">"Pregled"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Prebacite se na radni"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Prebacite se na lični"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Prebacite se na radni profil"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Prebacite se na lični profil profil"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Blokirao je administrator"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Pristupanje poslovnim podacima iz lične aplikacije nije dozvoljeno"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Pristupanje ličnim podacima iz poslovne aplikacije nije dozvoljeno"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Provjerite internetsku vezu i pokušajte ponovo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Pokušaj ponovo"</string> <string name="not_selected" msgid="2244008151669896758">"nije odabrano"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Pripremanje odabranih medijskih fajlova"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Spremno: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> od <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Sigurnosne kopije fotografija su sada uključene"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Možete odabrati fotografije s računa <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> u aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Odaberite aplikaciju"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Odaberite račun"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Promijenite račun"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Dohvatanje svih fotografija"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Dozvoliti da <xliff:g id="APP_NAME_0">^1</xliff:g> izmijeni ovaj audio fajl?}one{Dozvoliti da <xliff:g id="APP_NAME_1">^1</xliff:g> izmijeni <xliff:g id="COUNT">^2</xliff:g> audio fajl?}few{Dozvoliti da <xliff:g id="APP_NAME_1">^1</xliff:g> izmijeni <xliff:g id="COUNT">^2</xliff:g> audio fajla?}other{Dozvoliti da <xliff:g id="APP_NAME_1">^1</xliff:g> izmijeni <xliff:g id="COUNT">^2</xliff:g> audio fajlova?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Mijenjanje audio fajla…}one{Mijenjanje <xliff:g id="COUNT">^1</xliff:g> audio fajla…}few{Mijenjanje <xliff:g id="COUNT">^1</xliff:g> audio fajla…}other{Mijenjanje <xliff:g id="COUNT">^1</xliff:g> audio fajlova…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Dozvoliti da <xliff:g id="APP_NAME_0">^1</xliff:g> izmijeni ovaj videozapis?}one{Dozvoliti da <xliff:g id="APP_NAME_1">^1</xliff:g> izmijeni <xliff:g id="COUNT">^2</xliff:g> videozapis?}few{Dozvoliti da <xliff:g id="APP_NAME_1">^1</xliff:g> izmijeni <xliff:g id="COUNT">^2</xliff:g> videozapisa?}other{Dozvoliti da <xliff:g id="APP_NAME_1">^1</xliff:g> izmijeni <xliff:g id="COUNT">^2</xliff:g> videozapisa?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Zaštita sigurnosti"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Obavještenja o izvornom konvertiranju"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Napredak izvornog konvertiranja"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Nije moguće učitati određene fotografije"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Razumijem"</string> </resources> diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 34a682c6e..b99c99d0d 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimèdia"</string> <string name="storage_description" msgid="4081716890357580107">"Emmagatzematge local"</string> <string name="app_label" msgid="9035307001052716210">"Emmagatzematge multimèdia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Contingut multimèdia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Selector de mitjans"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Desconegut"</string> <string name="root_images" msgid="5861633549189045666">"Imatges"</string> @@ -40,12 +40,15 @@ <string name="deny" msgid="6040983710442068936">"Denega"</string> <string name="picker_browse" msgid="5554477454636075934">"Navega…"</string> <string name="picker_settings" msgid="6443463167344790260">"Aplicació multimèdia al núvol"</string> - <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Aplicació multimèdia al núvol"</string> + <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"App multimèdia al núvol"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Aplicació multimèdia al núvol"</string> <string name="picker_settings_description" msgid="2916686824777214585">"Accedeix al contingut multimèdia al núvol si una aplicació o un lloc web et demana que seleccionis fotos o vídeos"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Accedeix al contingut multimèdia al núvol des de"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Cap"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"No s\'ha pogut canviar l\'app multimèdia al núvol."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Selector de mitjans"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Selector de mitjans"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"S\'està sincronitzant el contingut multimèdia…"</string> <string name="add" msgid="2894574044585549298">"Afegeix"</string> <string name="deselect" msgid="4297825044827769490">"Desselecciona"</string> <string name="deselected" msgid="8488133193326208475">"Desseleccionat"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Comprova la connexió a Internet i torna-ho a provar"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Torna-ho a provar"</string> <string name="not_selected" msgid="2244008151669896758">"no seleccionat"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"S\'està preparant el contingut multimèdia seleccionat"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> de <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> a punt"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Ara s\'ha inclòs la còpia de seguretat de les fotos"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Pots seleccionar fotos del compte de <xliff:g id="APP_NAME">%1$s</xliff:g> de <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Tria una aplicació"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Tria un compte"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Canvia de compte"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"S\'estan obtenint totes les teves fotos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Vols permetre que <xliff:g id="APP_NAME_0">^1</xliff:g> modifiqui aquest fitxer d\'àudio?}many{Vols permetre que <xliff:g id="APP_NAME_1">^1</xliff:g> modifiqui <xliff:g id="COUNT">^2</xliff:g> fitxers d\'àudio?}other{Vols permetre que <xliff:g id="APP_NAME_1">^1</xliff:g> modifiqui <xliff:g id="COUNT">^2</xliff:g> fitxers d\'àudio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{S\'està modificant el fitxer d\'àudio…}many{S\'estan modificant <xliff:g id="COUNT">^1</xliff:g> fitxers d\'àudio…}other{S\'estan modificant <xliff:g id="COUNT">^1</xliff:g> fitxers d\'àudio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Vols permetre que <xliff:g id="APP_NAME_0">^1</xliff:g> modifiqui aquest vídeo?}many{Vols permetre que <xliff:g id="APP_NAME_1">^1</xliff:g> modifiqui <xliff:g id="COUNT">^2</xliff:g> vídeos?}other{Vols permetre que <xliff:g id="APP_NAME_1">^1</xliff:g> modifiqui <xliff:g id="COUNT">^2</xliff:g> vídeos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protecció de seguretat"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertes de transcodificació nativa"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progrés de la transcodificació nativa"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"No es poden carregar algunes fotos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Entesos"</string> </resources> diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 05f934c38..0363ca530 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Média"</string> <string name="storage_description" msgid="4081716890357580107">"Místní úložiště"</string> <string name="app_label" msgid="9035307001052716210">"Úložiště médií"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Média"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Nástroj pro výběr médií"</string> <string name="artist_label" msgid="8105600993099120273">"Interpret"</string> <string name="unknown" msgid="2059049215682829375">"Neznámý"</string> <string name="root_images" msgid="5861633549189045666">"Obrázky"</string> @@ -42,10 +42,13 @@ <string name="picker_settings" msgid="6443463167344790260">"Aplikace pro cloudová média"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Aplikace pro cloudová média"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Aplikace pro cloudová média"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Když vás aplikace nebo web požádá o výběr fotografií nebo videí, přejít na vaše cloudová média"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Když vás aplikace nebo web požádá o výběr fotografií nebo videí, můžete přejít na svoje cloudová média"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Přístup ke cloudovým médiím z"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Žádný"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Aplikaci pro cloudová média nyní nelze změnit."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Nástroj pro výběr médií"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Nástroj pro výběr médií"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synchronizace médií…"</string> <string name="add" msgid="2894574044585549298">"Přidat"</string> <string name="deselect" msgid="4297825044827769490">"Zrušit výběr"</string> <string name="deselected" msgid="8488133193326208475">"Výběr zrušen"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Zkontrolujte připojení k internetu a zkuste to znovu"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Zkusit znovu"</string> <string name="not_selected" msgid="2244008151669896758">"nevybráno"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Příprava vámi vybraných médií"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Připraveno: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> z <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Teď jsou zde zahrnuty zálohované fotky"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Můžete vybrat fotky z účtu <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Vybrat aplikaci"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Vybrat účet"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Změnit účet"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Načítání všech fotek"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Povolit aplikaci <xliff:g id="APP_NAME_0">^1</xliff:g> upravit tento zvukový soubor?}few{Povolit aplikaci <xliff:g id="APP_NAME_1">^1</xliff:g> upravit <xliff:g id="COUNT">^2</xliff:g> zvukové soubory?}many{Povolit aplikaci <xliff:g id="APP_NAME_1">^1</xliff:g> upravit <xliff:g id="COUNT">^2</xliff:g> zvukového souboru?}other{Povolit aplikaci <xliff:g id="APP_NAME_1">^1</xliff:g> upravit <xliff:g id="COUNT">^2</xliff:g> zvukových souborů?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Úprava zvukového souboru…}few{Úprava <xliff:g id="COUNT">^1</xliff:g> zvukových souborů…}many{Úprava <xliff:g id="COUNT">^1</xliff:g> zvukového souboru…}other{Úprava <xliff:g id="COUNT">^1</xliff:g> zvukových souborů…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Povolit aplikaci <xliff:g id="APP_NAME_0">^1</xliff:g> upravit toto video?}few{Povolit aplikaci <xliff:g id="APP_NAME_1">^1</xliff:g> upravit <xliff:g id="COUNT">^2</xliff:g> videa?}many{Povolit aplikaci <xliff:g id="APP_NAME_1">^1</xliff:g> upravit <xliff:g id="COUNT">^2</xliff:g> videa?}other{Povolit aplikaci <xliff:g id="APP_NAME_1">^1</xliff:g> upravit <xliff:g id="COUNT">^2</xliff:g> videí?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Bezpečnostní ochrana"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Upozornění na nativní překódování"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Průběh nativního překódování"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Některé fotografie nelze načíst"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Rozumím"</string> </resources> diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 65d3a01b1..9417aab79 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Medier"</string> <string name="storage_description" msgid="4081716890357580107">"Lokalt lager"</string> <string name="app_label" msgid="9035307001052716210">"Medielagring"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Mediefiler"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Medievælger"</string> <string name="artist_label" msgid="8105600993099120273">"Kunstner"</string> <string name="unknown" msgid="2059049215682829375">"Ukendt"</string> <string name="root_images" msgid="5861633549189045666">"Billeder"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Få adgang til medier i skyen via"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ingen"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Skymedieappen kunne ikke ændres"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Medievælger"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Medievælger"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Mediet synkroniseres…"</string> <string name="add" msgid="2894574044585549298">"Tilføj"</string> <string name="deselect" msgid="4297825044827769490">"Fravælg"</string> <string name="deselected" msgid="8488133193326208475">"Fravalgt"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Tjek din internetforbindelse, og prøv igen"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Prøv igen"</string> <string name="not_selected" msgid="2244008151669896758">"ikke valgt"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Dine valgte medier gøres klar"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> af <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> er klar"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Sikkerhedskopierede billeder er nu inkluderet"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Du kan vælge billeder fra <xliff:g id="APP_NAME">%1$s</xliff:g>-kontoen <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Vælg app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Vælg en konto"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Skift konto"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Indlæser alle dine billeder"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Vil du give <xliff:g id="APP_NAME_0">^1</xliff:g> tilladelse til at ændre denne lydfil?}one{Vil du give <xliff:g id="APP_NAME_1">^1</xliff:g> tilladelse til at ændre <xliff:g id="COUNT">^2</xliff:g> lydfil?}other{Vil du give <xliff:g id="APP_NAME_1">^1</xliff:g> tilladelse til at ændre <xliff:g id="COUNT">^2</xliff:g> lydfiler?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Ændrer lydfilen…}one{Ændrer <xliff:g id="COUNT">^1</xliff:g> lydfil…}other{Ændrer <xliff:g id="COUNT">^1</xliff:g> lydfiler…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Vil du give <xliff:g id="APP_NAME_0">^1</xliff:g> tilladelse til at ændre denne video?}one{Vil du give <xliff:g id="APP_NAME_1">^1</xliff:g> tilladelse til at ændre <xliff:g id="COUNT">^2</xliff:g> video?}other{Vil du give <xliff:g id="APP_NAME_1">^1</xliff:g> tilladelse til at ændre <xliff:g id="COUNT">^2</xliff:g> videoer?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Beskyttelse"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Underretninger om indbygget omkodning"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Status på indbygget omkodning"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Nogle billeder kan ikke indlæses"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 716a0f23a..9a63210d6 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Medien"</string> <string name="storage_description" msgid="4081716890357580107">"Lokaler Speicher"</string> <string name="app_label" msgid="9035307001052716210">"Medienspeicher"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Medien"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Media-Auswahl"</string> <string name="artist_label" msgid="8105600993099120273">"Interpret"</string> <string name="unknown" msgid="2059049215682829375">"Unbekannt"</string> <string name="root_images" msgid="5861633549189045666">"Bilder"</string> @@ -42,10 +42,13 @@ <string name="picker_settings" msgid="6443463167344790260">"Cloud-Medien-App"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Cloud-Medien-App"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Cloud-Medien-App"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Zugriff auf Cloudmedien, wenn dich eine App oder Website darum bittet, Fotos oder Videos auszuwählen"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Zugriff auf Cloud-Medien, wenn dich eine App oder Website darum bittet, Fotos oder Videos auszuwählen"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Zugriff auf Cloud-Medien aus"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Keine"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Ändern der Cloud-Medien-App derzeit nicht möglich."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Media-Auswahl"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Media-Auswahl"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Medien werden synchronisiert…"</string> <string name="add" msgid="2894574044585549298">"Hinzufügen"</string> <string name="deselect" msgid="4297825044827769490">"Auswahl aufheben"</string> <string name="deselected" msgid="8488133193326208475">"Auswahl aufgehoben"</string> @@ -93,19 +96,21 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Prüfe deine Internetverbindung und versuche es noch einmal"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Wiederholen"</string> <string name="not_selected" msgid="2244008151669896758">"nicht ausgewählt"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Ausgewählte Medien werden vorbereitet"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> von <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> fertig"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Gesicherte Fotos jetzt mit berücksichtigt"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Du kannst Fotos aus dem <xliff:g id="APP_NAME">%1$s</xliff:g>-Konto <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> auswählen"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g>-Konto aktualisiert"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Fotos von <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> sind jetzt hier mit berücksichtigt"</string> - <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"Cloudmedien-App auswählen"</string> - <string name="picker_banner_cloud_choose_app_desc" msgid="2359212653555524926">"Damit gesicherte Fotos hier mit berücksichtigt werden, wähle eine Cloudmedien-App in den Einstellungen aus"</string> + <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"Cloud-Medien-App auswählen"</string> + <string name="picker_banner_cloud_choose_app_desc" msgid="2359212653555524926">"Damit gesicherte Fotos hier mit berücksichtigt werden, wähle eine Cloud-Medien-App in den Einstellungen aus"</string> <string name="picker_banner_cloud_choose_account_title" msgid="5010901185639577685">"<xliff:g id="APP_NAME">%1$s</xliff:g>-Konto auswählen"</string> <string name="picker_banner_cloud_choose_account_desc" msgid="8868134443673142712">"Damit Fotos von <xliff:g id="APP_NAME">%1$s</xliff:g> hier mit berücksichtigt werden, wähle eine Konto in der App aus"</string> <string name="picker_banner_cloud_dismiss_button" msgid="2935903078288463882">"Schließen"</string> <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"App auswählen"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Konto auswählen"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Konto ändern"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Alle deine Fotos werden geladen"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Darf <xliff:g id="APP_NAME_0">^1</xliff:g> diese Audiodatei ändern?}other{Darf <xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> Audiodateien ändern?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Audiodatei wird geändert…}other{<xliff:g id="COUNT">^1</xliff:g> Audiodateien werden geändert…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Darf <xliff:g id="APP_NAME_0">^1</xliff:g> dieses Video ändern?}other{Darf <xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> Videos ändern?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Schutz"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Warnmeldungen bei nativer Transcodierung"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Fortschritt bei nativer Transcodierung"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Einige Fotos konnten nicht geladen werden"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Ok"</string> </resources> diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index a4beb6a82..f8aefdbc3 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Μέσα"</string> <string name="storage_description" msgid="4081716890357580107">"Τοπικός χώρος αποθήκευσης"</string> <string name="app_label" msgid="9035307001052716210">"Αποθηκευτικός χώρος μέσων"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Μέσα"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Εργαλείο επιλογής μέσων"</string> <string name="artist_label" msgid="8105600993099120273">"Καλλιτέχνης"</string> <string name="unknown" msgid="2059049215682829375">"Άγνωστο"</string> <string name="root_images" msgid="5861633549189045666">"Εικόνες"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Πρόσβαση σε μέσα στο cloud από"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Καμία"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Η αλλαγή της εφαρμογής μέσων cloud ήταν αδύνατη."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Εργαλείο επιλογής μέσων"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Εργαλείο επιλογής μέσων"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Συγχρονισμός μέσων…"</string> <string name="add" msgid="2894574044585549298">"Προσθήκη"</string> <string name="deselect" msgid="4297825044827769490">"Αποεπιλογή"</string> <string name="deselected" msgid="8488133193326208475">"Αποεπιλέχθηκε"</string> @@ -55,7 +58,7 @@ <string name="recent" msgid="6694613584743207874">"Πρόσφατα"</string> <string name="picker_photos_empty_message" msgid="5980619500554575558">"Δεν υπάρχουν φωτογραφίες ή βίντεο"</string> <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Δεν υπάρχουν υποστηριζόμενες φωτογραφίες ή βίντεο"</string> - <string name="picker_albums_empty_message" msgid="8341079772950966815">"Δεν υπάρχουν λευκώματα"</string> + <string name="picker_albums_empty_message" msgid="8341079772950966815">"Δεν υπάρχουν άλμπουμ"</string> <string name="picker_view_selected" msgid="2266031384396143883">"Προβολή επιλεγμένων"</string> <string name="picker_photos" msgid="7415035516411087392">"Φωτογραφίες"</string> <string name="picker_albums" msgid="4822511902115299142">"Άλμπουμ"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Ελέγξτε τη σύνδεσή σας στο διαδίκτυο και δοκιμάστε ξανά"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Επανάληψη"</string> <string name="not_selected" msgid="2244008151669896758">"μη επιλεγμένο"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Προετοιμασία των μέσων που επιλέξατε"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> από <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> έτοιμα"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Συμπεριλαμβάνονται πλέον φωτογραφίες που έχουν αντίγραφα ασφαλείας"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Μπορείτε να επιλέξετε φωτογραφίες από τον λογαριασμό <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Επιλογή εφαρμογής"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Επιλογή λογαριασμού"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Αλλαγή λογαριασμού"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Γίνεται λήψη όλων των φωτογραφιών σας"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Να επιτραπεί στην εφαρμογή <xliff:g id="APP_NAME_0">^1</xliff:g> η τροποποίηση αυτού του αρχείου ήχου;}other{Να επιτραπεί στην εφαρμογή <xliff:g id="APP_NAME_1">^1</xliff:g> η τροποποίηση <xliff:g id="COUNT">^2</xliff:g> αρχείων ήχου;}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Τροποποίηση αρχείου ήχου…}other{Τροποποίηση <xliff:g id="COUNT">^1</xliff:g> αρχείων ήχου…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Να επιτραπεί στην εφαρμογή <xliff:g id="APP_NAME_0">^1</xliff:g> η τροποποίηση αυτού του βίντεο;}other{Να επιτραπεί στην εφαρμογή <xliff:g id="APP_NAME_1">^1</xliff:g> η τροποποίηση <xliff:g id="COUNT">^2</xliff:g> βίντεο;}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Safety Protection"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Ειδοποιήσεις εγγενούς διακωδικοποίησης"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Πρόοδος εγγενούς διακωδικοποίησης"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Δεν είναι δυνατή η φόρτωση ορισμένων φωτογραφιών"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Το κατάλαβα"</string> </resources> diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 28f903e32..390d946cd 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Local storage"</string> <string name="app_label" msgid="9035307001052716210">"Media Storage"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Media picker"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Unknown"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Access cloud media from"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"None"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Could not change cloud media app at this time."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Media Picker"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Media Picker"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Syncing media…"</string> <string name="add" msgid="2894574044585549298">"Add"</string> <string name="deselect" msgid="4297825044827769490">"Deselect"</string> <string name="deselected" msgid="8488133193326208475">"Deselected"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Please check your Internet connection and try again"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Retry"</string> <string name="not_selected" msgid="2244008151669896758">"not selected"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparing your selected media"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> of <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ready"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Backed up photos now included"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"You can select photos from <xliff:g id="APP_NAME">%1$s</xliff:g> account <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Choose app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Choose account"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Change account"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Getting all your photos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this audio file?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> audio files?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modifying audio file…}other{Modifying <xliff:g id="COUNT">^1</xliff:g> audio files…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this video?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> videos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Safety protection"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native transcode alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native transcode progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Can\'t load some Photos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Got it"</string> </resources> diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index 2a0225f8a..209bf8f0e 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Local storage"</string> <string name="app_label" msgid="9035307001052716210">"Media Storage"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Media picker"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Unknown"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Access cloud media from"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"None"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Could not change cloud media app at this time."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Media picker"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Media picker"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Syncing media…"</string> <string name="add" msgid="2894574044585549298">"Add"</string> <string name="deselect" msgid="4297825044827769490">"Deselect"</string> <string name="deselected" msgid="8488133193326208475">"Deselected"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Check your internet connection and try again"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Retry"</string> <string name="not_selected" msgid="2244008151669896758">"not selected"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparing your selected media"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> of <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ready"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Backed up photos now included"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"You can select photos from <xliff:g id="APP_NAME">%1$s</xliff:g> account <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Choose app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Choose account"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Change account"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Getting all your photos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this audio file?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> audio files?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modifying audio file…}other{Modifying <xliff:g id="COUNT">^1</xliff:g> audio files…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this video?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> videos?}}"</string> @@ -149,4 +154,7 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Safety protection"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native Transcode Alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native Transcode Progress"</string> + <string name="dialog_error_message" msgid="5120432204743681606">"Try again later. Your photos will be available once the issue is resolved."</string> + <string name="dialog_error_title" msgid="636349284077820636">"Can\'t load some Photos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Got it"</string> </resources> diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 28f903e32..390d946cd 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Local storage"</string> <string name="app_label" msgid="9035307001052716210">"Media Storage"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Media picker"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Unknown"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Access cloud media from"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"None"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Could not change cloud media app at this time."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Media Picker"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Media Picker"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Syncing media…"</string> <string name="add" msgid="2894574044585549298">"Add"</string> <string name="deselect" msgid="4297825044827769490">"Deselect"</string> <string name="deselected" msgid="8488133193326208475">"Deselected"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Please check your Internet connection and try again"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Retry"</string> <string name="not_selected" msgid="2244008151669896758">"not selected"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparing your selected media"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> of <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ready"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Backed up photos now included"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"You can select photos from <xliff:g id="APP_NAME">%1$s</xliff:g> account <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Choose app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Choose account"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Change account"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Getting all your photos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this audio file?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> audio files?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modifying audio file…}other{Modifying <xliff:g id="COUNT">^1</xliff:g> audio files…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this video?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> videos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Safety protection"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native transcode alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native transcode progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Can\'t load some Photos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Got it"</string> </resources> diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 28f903e32..390d946cd 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Local storage"</string> <string name="app_label" msgid="9035307001052716210">"Media Storage"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Media picker"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Unknown"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Access cloud media from"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"None"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Could not change cloud media app at this time."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Media Picker"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Media Picker"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Syncing media…"</string> <string name="add" msgid="2894574044585549298">"Add"</string> <string name="deselect" msgid="4297825044827769490">"Deselect"</string> <string name="deselected" msgid="8488133193326208475">"Deselected"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Please check your Internet connection and try again"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Retry"</string> <string name="not_selected" msgid="2244008151669896758">"not selected"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparing your selected media"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> of <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ready"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Backed up photos now included"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"You can select photos from <xliff:g id="APP_NAME">%1$s</xliff:g> account <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Choose app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Choose account"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Change account"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Getting all your photos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this audio file?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> audio files?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modifying audio file…}other{Modifying <xliff:g id="COUNT">^1</xliff:g> audio files…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this video?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> videos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Safety protection"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native transcode alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native transcode progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Can\'t load some Photos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Got it"</string> </resources> diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index bb86af760..938928f33 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Local storage"</string> <string name="app_label" msgid="9035307001052716210">"Media Storage"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Media picker"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Unknown"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Access cloud media from"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"None"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Could not change cloud media app at this time."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Media picker"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Media picker"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Syncing media…"</string> <string name="add" msgid="2894574044585549298">"Add"</string> <string name="deselect" msgid="4297825044827769490">"Deselect"</string> <string name="deselected" msgid="8488133193326208475">"Deselected"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Check your internet connection and try again"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Retry"</string> <string name="not_selected" msgid="2244008151669896758">"not selected"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparing your selected media"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> of <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ready"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Backed up photos now included"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"You can select photos from <xliff:g id="APP_NAME">%1$s</xliff:g> account <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Choose app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Choose account"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Change account"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Getting all your photos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this audio file?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> audio files?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modifying audio file…}other{Modifying <xliff:g id="COUNT">^1</xliff:g> audio files…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Allow <xliff:g id="APP_NAME_0">^1</xliff:g> to modify this video?}other{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> videos?}}"</string> @@ -149,4 +154,7 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Safety protection"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native Transcode Alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native Transcode Progress"</string> + <string name="dialog_error_message" msgid="5120432204743681606">"Try again later. Your photos will be available once the issue is resolved."</string> + <string name="dialog_error_title" msgid="636349284077820636">"Can\'t load some Photos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Got it"</string> </resources> diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 791a94443..90be78bd5 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimedia"</string> <string name="storage_description" msgid="4081716890357580107">"Almacenamiento local"</string> <string name="app_label" msgid="9035307001052716210">"Almacenamiento multimedia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Multimedia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Selector de medios"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Desconocido"</string> <string name="root_images" msgid="5861633549189045666">"Imágenes"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Accede a los medios en la nube desde"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ninguna"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"No se pudo cambiar la app de música en la nube."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Selector de medios"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Selector de medios"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sincronizando contenido multimedia…"</string> <string name="add" msgid="2894574044585549298">"Agregar"</string> <string name="deselect" msgid="4297825044827769490">"Anular la selección"</string> <string name="deselected" msgid="8488133193326208475">"Sin seleccionar"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Revisa la conexión a Internet y vuelve a intentarlo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Reintentar"</string> <string name="not_selected" msgid="2244008151669896758">"sin seleccionar"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparando el contenido multimedia seleccionado"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> de <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> listos"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Ahora se incluyen las fotos con copia de seguridad"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Puedes seleccionar fotos de <xliff:g id="APP_NAME">%1$s</xliff:g> desde la cuenta de <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Puedes seleccionar imágenes de <xliff:g id="APP_NAME">%1$s</xliff:g> desde la cuenta de <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"Se actualizó la cuenta de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Ahora se incluyen aquí las fotos de <xliff:g id="USER_ACCOUNT">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"Elige una app multimedia en la nube"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Elegir una app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Elegir cuenta"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Cambiar cuenta"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Obteniendo todas tus fotos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{¿Deseas permitir que <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este archivo de audio?}many{¿Deseas permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> archivos de audio?}other{¿Deseas permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> archivos de audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modificando el archivo de audio…}many{Modificando <xliff:g id="COUNT">^1</xliff:g> archivos de audio…}other{Modificando <xliff:g id="COUNT">^1</xliff:g> archivos de audio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{¿Deseas permitir que <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este video?}many{¿Deseas permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> videos?}other{¿Deseas permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> videos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protección de seguridad"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native Transcode Alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native Transcode Progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Se produjo un error durante la carga de algunas fotos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Entendido"</string> </resources> diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 241897de5..64349b44a 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimedia"</string> <string name="storage_description" msgid="4081716890357580107">"Almacenamiento local"</string> <string name="app_label" msgid="9035307001052716210">"Almacenamiento multimedia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Multimedia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Selector de medios"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Desconocido"</string> <string name="root_images" msgid="5861633549189045666">"Imágenes"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Accede al contenido multimedia en la nube desde"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ninguna"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"No se puede cambiar la app multimedia en la nube."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Selector de medios"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Selector de medios"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sincronizando contenido multimedia…"</string> <string name="add" msgid="2894574044585549298">"Añadir"</string> <string name="deselect" msgid="4297825044827769490">"Desmarcar"</string> <string name="deselected" msgid="8488133193326208475">"Desmarcado"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Fotos"</string> <string name="picker_albums" msgid="4822511902115299142">"Álbumes"</string> <string name="picker_preview" msgid="6257414886055861039">"Vista previa"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Cambiar al de trabajo"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Cambiar al personal"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Cambiar a perfil de trabajo"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Cambiar a perfil personal"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Bloqueado por tu administrador"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"No se puede acceder a datos de trabajo desde una aplicación personal"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"No se puede acceder a datos personales desde una aplicación de trabajo"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Comprueba tu conexión a Internet y vuelve a intentarlo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Reintentar"</string> <string name="not_selected" msgid="2244008151669896758">"no seleccionado"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparando el contenido multimedia seleccionado"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> de <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> listos"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Ahora se incluye la copia de seguridad de las fotos"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Puedes seleccionar fotos de la cuenta de <xliff:g id="APP_NAME">%1$s</xliff:g> de <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Elegir aplicación"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Elegir cuenta"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Cambiar de cuenta"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Cargando todas tus fotos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{¿Permitir que <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este archivo de audio?}many{¿Permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> archivos de audio?}other{¿Permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> archivos de audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modificando archivo de audio…}many{Modificando <xliff:g id="COUNT">^1</xliff:g> archivos de audio…}other{Modificando <xliff:g id="COUNT">^1</xliff:g> archivos de audio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{¿Permitir que <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este vídeo?}many{¿Permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}other{¿Permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protección de seguridad"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertas de transcodificación nativa"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progreso de transcodificación nativa"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"No se pueden cargar algunas fotos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Entendido"</string> </resources> diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index e74c07158..321984aea 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Meedia"</string> <string name="storage_description" msgid="4081716890357580107">"Kohalik salvestusruum"</string> <string name="app_label" msgid="9035307001052716210">"Meediumi salvestusruum"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Meedia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Meediavalija"</string> <string name="artist_label" msgid="8105600993099120273">"Esitaja"</string> <string name="unknown" msgid="2059049215682829375">"Teadmata"</string> <string name="root_images" msgid="5861633549189045666">"Pildid"</string> @@ -39,13 +39,16 @@ <string name="allow" msgid="8885707816848569619">"Luba"</string> <string name="deny" msgid="6040983710442068936">"Keela"</string> <string name="picker_browse" msgid="5554477454636075934">"Sirvimine …"</string> - <string name="picker_settings" msgid="6443463167344790260">"Pilvemeediarakendus"</string> - <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Pilvemeediarakendus"</string> - <string name="picker_settings_title" msgid="5647700706470673258">"Pilvemeediarakendus"</string> + <string name="picker_settings" msgid="6443463167344790260">"Pilvemeedia rakendus"</string> + <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Pilvemeedia rakendus"</string> + <string name="picker_settings_title" msgid="5647700706470673258">"Pilvemeedia rakendus"</string> <string name="picker_settings_description" msgid="2916686824777214585">"Juurdepääs teie pilves olevale meediale, kui rakendus või veebisait palub teil fotosid või videoid valida"</string> - <string name="picker_settings_selection_message" msgid="245453573086488596">"Pilvemeediarakendus:"</string> + <string name="picker_settings_selection_message" msgid="245453573086488596">"Pilvemeedia rakendus:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Pole"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Pilvepõhist meediarakendust ei saanud muuta."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Meediavalija"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Meediavalija"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Meediumi sünkroonimine …"</string> <string name="add" msgid="2894574044585549298">"Lisa"</string> <string name="deselect" msgid="4297825044827769490">"Tühista valik"</string> <string name="deselected" msgid="8488133193326208475">"Valik on tühistatud"</string> @@ -63,7 +66,7 @@ <string name="picker_work_profile" msgid="2083221066869141576">"Lülituge tööprofiilile"</string> <string name="picker_personal_profile" msgid="639484258397758406">"Lülituge isiklikule profiilile"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Blokeeris teie administraator"</string> - <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Juurdepääs tööandmetele isikliku rakenduse kaudu pole lubatud"</string> + <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Juurdepääs tööandmetele isikliku rakenduse kaudu pole lubatud."</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Juurdepääs isiklikele andmetele töörakenduse kaudu pole lubatud"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"Töörakendused on peatatud"</string> <string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"Tööfotode avamiseks lülitage töörakendused sisse ja proovige uuesti"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Kontrollige internetiühendust ja proovige uuesti"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Proovi uuesti"</string> <string name="not_selected" msgid="2244008151669896758">"pole valitud"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Valitud meedia ettevalmistamine"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>-st on valmis"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Varundatud fotod on nüüd kaasatud"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Saate valida fotosid rakendusest <xliff:g id="APP_NAME">%1$s</xliff:g> konto <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> kaudu"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Saate valida konto <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> fotosid rakendusest <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> kontot värskendati"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Kasutaja <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> fotod on nüüd siia kaasatud"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"Valige pilvemeediarakendus"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Valige rakendus"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Konto valimine"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Konto vahetamine"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Kõigi fotode toomine"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Kas lubada rakendusel <xliff:g id="APP_NAME_0">^1</xliff:g> seda helifaili muuta?}other{Kas lubada rakendusel <xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> helifaili muuta?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Helifaili muutmine …}other{<xliff:g id="COUNT">^1</xliff:g> helifaili muutmine …}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Kas lubada rakendusel <xliff:g id="APP_NAME_0">^1</xliff:g> seda videot muuta?}other{Kas lubada rakendusel <xliff:g id="APP_NAME_1">^1</xliff:g> <xliff:g id="COUNT">^2</xliff:g> videot muuta?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Ohutuskaitse"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Omakoodi transkodeerimise hoiatused"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Omakoodi transkodeerimise edenemine"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Mõnda fotot ei saa laadida"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Selge"</string> </resources> diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 1a7bc4822..c1208182f 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimedia-edukia"</string> <string name="storage_description" msgid="4081716890357580107">"Biltegi lokala"</string> <string name="app_label" msgid="9035307001052716210">"Multimediaren memoria-unitatea"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Multimedia-edukia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Multimedia-edukiaren hautatzailea"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Ezezaguna"</string> <string name="root_images" msgid="5861633549189045666">"Irudiak"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Atzitu honen bidez gordetako hodeiko multimedia-edukia:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Bat ere ez"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Ezin izan da aldatu hodeiko multimedia-aplikazioa."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Multimedia-edukiaren hautatzailea"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Multimedia-edukiaren hautatzailea"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Multimedia-edukia sinkronizatzen…"</string> <string name="add" msgid="2894574044585549298">"Gehitu"</string> <string name="deselect" msgid="4297825044827769490">"Desautatu"</string> <string name="deselected" msgid="8488133193326208475">"Desautatuta"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Egiaztatu Internetera konektatuta zaudela eta saiatu berriro"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Saiatu berriro"</string> <string name="not_selected" msgid="2244008151669896758">"hautatu gabe"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Hautatutako multimedia-edukia prestatzen"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> prest"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Orain, babeskopiak dituzten argazkiak sartuta daude"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Orain, barnean hartzen dira babeskopiak dituzten argazkiak"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> kontuko argazkiak hauta ditzakezu"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"Eguneratu da <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko kontua"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Orain, <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> kontuko argazkiak hemen sartuta daude"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Aukeratu aplikazio bat"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Aukeratu kontu bat"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Aldatu kontua"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Argazki guztiak eskuratzen"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Audio-fitxategiari aldaketak egiteko baimena eman nahi diozu <xliff:g id="APP_NAME_0">^1</xliff:g> aplikazioari?}other{<xliff:g id="COUNT">^2</xliff:g> audio-fitxategiri aldaketak egiteko baimena eman nahi diozu <xliff:g id="APP_NAME_1">^1</xliff:g> aplikazioari?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Audio-fitxategia aldatzen…}other{<xliff:g id="COUNT">^1</xliff:g> audio-fitxategi aldatzen…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Bideoari aldaketak egiteko baimena eman nahi diozu <xliff:g id="APP_NAME_0">^1</xliff:g> aplikazioari?}other{<xliff:g id="COUNT">^2</xliff:g> bideori aldaketak egiteko baimena eman nahi diozu <xliff:g id="APP_NAME_1">^1</xliff:g> aplikazioari?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Segurtasun-babesa"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Transkodetze-alerta natiboak"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Transkodetze natiboaren garapena"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Ezin dira kargatu argazki batzuk"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Ados"</string> </resources> diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 94e81c1ac..91d0d28ad 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -19,11 +19,11 @@ <string name="uid_label" msgid="8421971615411294156">"رسانه"</string> <string name="storage_description" msgid="4081716890357580107">"فضای ذخیرهسازی محلی"</string> <string name="app_label" msgid="9035307001052716210">"فضای ذخیرهسازی رسانه"</string> - <string name="picker_app_label" msgid="4254039089502164761">"رسانه"</string> + <string name="picker_app_label" msgid="1195424381053599122">"انتخابگر رسانه"</string> <string name="artist_label" msgid="8105600993099120273">"هنرمند"</string> <string name="unknown" msgid="2059049215682829375">"نامشخص"</string> <string name="root_images" msgid="5861633549189045666">"تصویر"</string> - <string name="root_videos" msgid="8792703517064649453">"ویدئو"</string> + <string name="root_videos" msgid="8792703517064649453">"ویدیوها"</string> <string name="root_audio" msgid="3505830755201326018">"صوت"</string> <string name="root_documents" msgid="3829103301363849237">"اسناد"</string> <string name="permission_required" msgid="1460820436132943754">"برای اصلاح یا حذف این مورد مجوز لازم است."</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"دسترسی به رسانه ابری از"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"هیچکدام"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"اکنون نمیتوانید برنامه رسانه ابری را تغییر دهید."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"انتخابگر رسانه"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"انتخابگر رسانه"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"درحال همگامسازی رسانه…"</string> <string name="add" msgid="2894574044585549298">"افزودن"</string> <string name="deselect" msgid="4297825044827769490">"لغو انتخاب"</string> <string name="deselected" msgid="8488133193326208475">"لغو انتخابشده"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"اتصال اینترنت را بررسی کنید و دوباره امتحان کنید"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"امتحان مجدد"</string> <string name="not_selected" msgid="2244008151669896758">"انتخاب نشده است"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"درحال آمادهسازی رسانه انتخابشده"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> مورد از <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> مورد آماده است"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"عکسهای پشتیبانگیریشده اکنون اضافه میشود"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"عکسهای پشتیبانگیریشده اکنون اضافه شدهاند"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"میتوانید عکسهای حساب <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="USER_ACCOUNT">%2$s</xliff:g>) را انتخاب کنید"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"حساب <xliff:g id="APP_NAME">%1$s</xliff:g> بهروز شد"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"عکسهای <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> اکنون در اینجا اضافه میشود"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"انتخاب برنامه"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"انتخاب حساب"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"تغییر حساب"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"درحال دریافت همه عکسهای شما"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{به <xliff:g id="APP_NAME_0">^1</xliff:g> اجازه میدهید این فایل صوتی را تغییر دهد؟}one{به <xliff:g id="APP_NAME_1">^1</xliff:g> اجازه میدهید <xliff:g id="COUNT">^2</xliff:g> فایل صوتی را تغییر دهد؟}other{به <xliff:g id="APP_NAME_1">^1</xliff:g> اجازه میدهید <xliff:g id="COUNT">^2</xliff:g> فایل صوتی را تغییر دهد؟}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{درحال اصلاح فایل صوتی…}one{درحال اصلاح <xliff:g id="COUNT">^1</xliff:g> فایل صوتی…}other{درحال اصلاح <xliff:g id="COUNT">^1</xliff:g> فایل صوتی…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{به <xliff:g id="APP_NAME_0">^1</xliff:g> اجازه میدهید این ویدیو را تغییر دهد؟}one{به <xliff:g id="APP_NAME_1">^1</xliff:g> اجازه میدهید <xliff:g id="COUNT">^2</xliff:g> ویدیو را تغییر دهد؟}other{به <xliff:g id="APP_NAME_1">^1</xliff:g> اجازه میدهید <xliff:g id="COUNT">^2</xliff:g> ویدیو را تغییر دهد؟}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"محافظت امنیتی"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"هشدارهای تراتبدیل محلی"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"پیشرفت تراتبدیل محلی"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"نمیتوان برخیاز عکسها را بار کرد"</string> + <string name="dialog_button_text" msgid="351366485240852280">"متوجهام"</string> </resources> diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index eda6c35f9..881a5ca26 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Paikallinen tallennustila"</string> <string name="app_label" msgid="9035307001052716210">"Median tallennustila"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Median valitsin"</string> <string name="artist_label" msgid="8105600993099120273">"Artisti"</string> <string name="unknown" msgid="2059049215682829375">"Tuntematon"</string> <string name="root_images" msgid="5861633549189045666">"Kuvat"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Pääsy pilvimediaan:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"–"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Pilvimediasovellusta ei voitu vaihtaa."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Median valitsin"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Median valitsin"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synkronoidaan mediaa…"</string> <string name="add" msgid="2894574044585549298">"Lisää"</string> <string name="deselect" msgid="4297825044827769490">"Poista valinta"</string> <string name="deselected" msgid="8488133193326208475">"Valinta poistettu"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Tarkista internetyhteytesi ja yritä uudelleen"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Yritä uudelleen"</string> <string name="not_selected" msgid="2244008151669896758">"ei valittu"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Valitsemaasi mediaa valmistellaan"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> valmiina"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Varmuuskopioidut kuvat löytyvät nyt täältä"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Voit valita sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> kuvat tililtä <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Valitse sovellus"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Valitse tili"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Vaihda tiliä"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Ladataan kaikkia kuvia"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Saako <xliff:g id="APP_NAME_0">^1</xliff:g> muokata tätä audiotiedostoa?}other{Saako <xliff:g id="APP_NAME_1">^1</xliff:g> muokata <xliff:g id="COUNT">^2</xliff:g> audiotiedostoa?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Muokataan audiotiedostoa…}other{Muokataan <xliff:g id="COUNT">^1</xliff:g> audiotiedostoa…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Saako <xliff:g id="APP_NAME_0">^1</xliff:g> muokata tätä videota?}other{Saako <xliff:g id="APP_NAME_1">^1</xliff:g> muokata <xliff:g id="COUNT">^2</xliff:g> videota?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Turvallisuuden varmistaminen"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Natiivin transkoodin ilmoitukset"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Natiivin transkoodin edistyminen"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Joitain kuvia ei voi ladata"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 88878c6ad..8ee7716a2 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimédia"</string> <string name="storage_description" msgid="4081716890357580107">"Stockage local"</string> <string name="app_label" msgid="9035307001052716210">"Stockage multimédia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Contenu multimédia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Sélecteur d\'éléments multimédias"</string> <string name="artist_label" msgid="8105600993099120273">"Artiste"</string> <string name="unknown" msgid="2059049215682829375">"Inconnu"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Accéder au contenu multimédia infonuagique à partir de"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Aucune"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Changement appli multimédia infonuagique imposs."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Sélecteur d\'éléments multimédias"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Sélecteur d\'éléments multimédias"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synchronisation du contenu multimédia en cours…"</string> <string name="add" msgid="2894574044585549298">"Ajouter"</string> <string name="deselect" msgid="4297825044827769490">"Désélectionner"</string> <string name="deselected" msgid="8488133193326208475">"Désélectionné"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Vérifiez votre connexion Internet et réessayez"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Réessayer"</string> <string name="not_selected" msgid="2244008151669896758">"non sélectionné"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Préparation du contenu multimédia sélectionné en cours…"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> sur <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> prêt(s)"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Les photos sauvegardées sont maintenant incluses"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Vous pouvez sélectionner des photos du compte <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Choisir une application"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Choisir un compte"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Changer de compte"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Chargement de vos photos en cours…"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Autoriser <xliff:g id="APP_NAME_0">^1</xliff:g> à modifier ce fichier audio?}one{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> fichier audio?}many{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> fichiers audio?}other{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> fichiers audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modification du fichier audio en cours…}one{Modification de <xliff:g id="COUNT">^1</xliff:g> fichier audio en cours…}many{Modification de <xliff:g id="COUNT">^1</xliff:g> fichiers audio en cours…}other{Modification de <xliff:g id="COUNT">^1</xliff:g> fichiers audio en cours…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Autoriser <xliff:g id="APP_NAME_0">^1</xliff:g> à modifier cette vidéo?}one{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> vidéo?}many{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> vidéos?}other{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> vidéos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protection de sécurité"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertes de transcodage natif"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progression du transcodage natif"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Impossible de charger certaines photos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index d66bcb72d..485c651d5 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimédia"</string> <string name="storage_description" msgid="4081716890357580107">"Stockage local"</string> <string name="app_label" msgid="9035307001052716210">"Stockage multimédia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Multimédia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Sélecteur de fichiers multimédias"</string> <string name="artist_label" msgid="8105600993099120273">"Artiste"</string> <string name="unknown" msgid="2059049215682829375">"Inconnu"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Accéder aux contenus multimédias cloud à partir de"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Aucune"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Impossible de changer l\'appli multimédia cloud."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Sélecteur de fichiers multimédias"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Sélecteur de fichiers multimédias"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synchronisation des fichiers multimédias…"</string> <string name="add" msgid="2894574044585549298">"Ajouter"</string> <string name="deselect" msgid="4297825044827769490">"Désélectionner"</string> <string name="deselected" msgid="8488133193326208475">"Désélectionné"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Photos"</string> <string name="picker_albums" msgid="4822511902115299142">"Albums"</string> <string name="picker_preview" msgid="6257414886055861039">"Aperçu"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Passer au professionnel"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Passer au personnel"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Passer au profil professionnel"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Passer au profil personnel"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Bloqué par votre administrateur"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Vous n\'êtes pas autorisé à accéder à des données professionnelles depuis une appli personnelle"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Vous n\'êtes pas autorisé à accéder à des données à caractère personnel depuis une appli professionnelle"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Vérifiez votre connexion Internet, puis réessayez"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Réessayer"</string> <string name="not_selected" msgid="2244008151669896758">"non sélectionné"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Préparation des fichiers multimédias que vous avez sélectionnés"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Prêt(s) : <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> sur <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Les photos sauvegardées sont désormais incluses"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Vous pouvez sélectionner des photos de <xliff:g id="APP_NAME">%1$s</xliff:g>, compte <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Vous pouvez sélectionner des photos issues du compte <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> dans l\'appli <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"Compte <xliff:g id="APP_NAME">%1$s</xliff:g> mis à jour"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Les photos de <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> sont désormais incluses ici"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"Sélectionner une appli multimédia cloud"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Sélectionner une appli"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Sélectionner un compte"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Changer de compte"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Chargement de toutes vos photos…"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Autoriser <xliff:g id="APP_NAME_0">^1</xliff:g> à modifier ce fichier audio ?}one{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> fichier audio ?}many{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> fichiers audio ?}other{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> fichiers audio ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modification du fichier audio…}one{Modification de <xliff:g id="COUNT">^1</xliff:g> fichier audio…}many{Modification de <xliff:g id="COUNT">^1</xliff:g> fichiers audio…}other{Modification de <xliff:g id="COUNT">^1</xliff:g> fichiers audio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Autoriser <xliff:g id="APP_NAME_0">^1</xliff:g> à modifier cette vidéo ?}one{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> vidéo ?}many{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> vidéos ?}other{Autoriser <xliff:g id="APP_NAME_1">^1</xliff:g> à modifier <xliff:g id="COUNT">^2</xliff:g> vidéos ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protection de sécurité"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertes de transcodage natif"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progression du transcodage natif"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Impossible de charger certaines photos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 2bf371a34..140ec55c0 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimedia"</string> <string name="storage_description" msgid="4081716890357580107">"Almacenamento local"</string> <string name="app_label" msgid="9035307001052716210">"Almacenamento multimedia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Contido multimedia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Seleccionador multimedia"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Descoñecida"</string> <string name="root_images" msgid="5861633549189045666">"Imaxes"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Acceder ao contido multimedia gardado na nube desde"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ningunha"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"App multimedia con servizo na nube non cambiada."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Seleccionador de contido multimedia"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Seleccionador de contido multimedia"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sincronizando contido multimedia…"</string> <string name="add" msgid="2894574044585549298">"Engadir"</string> <string name="deselect" msgid="4297825044827769490">"Anular selección"</string> <string name="deselected" msgid="8488133193326208475">"Anulouse a selección"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Comproba a conexión a Internet e téntao de novo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Tentar de novo"</string> <string name="not_selected" msgid="2244008151669896758">"elemento non seleccionado"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparando recursos seleccionados"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Elementos listos: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> de <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Agora inclúense as fotos con copia de seguranza"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Podes seleccionar fotos da seguinte conta de <xliff:g id="APP_NAME">%1$s</xliff:g>: <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Escoller aplicación"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Seleccionar conta"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Cambiar de conta"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Cargando todas as fotos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Queres permitir que <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este ficheiro de audio?}other{Queres permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> ficheiros de audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modificando 1 ficheiro de audio…}other{Modificando <xliff:g id="COUNT">^1</xliff:g> ficheiros de audio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Queres permitir que <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este vídeo?}other{Queres permitir que <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protección de seguranza"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertas de transcodificación nativa"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progreso da transcodificación nativa"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Non se poden cargar algunhas fotos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Entendido"</string> </resources> diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index a1275df38..1ab9a5c56 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"મીડિયા"</string> <string name="storage_description" msgid="4081716890357580107">"સ્થાનિક સ્ટોરેજ"</string> <string name="app_label" msgid="9035307001052716210">"મીડિયા સ્ટોરેજ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"મીડિયા"</string> + <string name="picker_app_label" msgid="1195424381053599122">"મીડિયા પિકર"</string> <string name="artist_label" msgid="8105600993099120273">"કલાકાર"</string> <string name="unknown" msgid="2059049215682829375">"અજાણ"</string> <string name="root_images" msgid="5861633549189045666">"છબીઓ"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"આમાંથી ક્લાઉડ મીડિયાને ઍક્સેસ કરો"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"એકપણ નહીં"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"આ સમયે ક્લાઉડ મીડિયા ઍપને બદલી શકાઈ નથી."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"મીડિયા પિકર"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"મીડિયા પિકર"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"મીડિયા સિંક કરી રહ્યાં છે…"</string> <string name="add" msgid="2894574044585549298">"ઉમેરો"</string> <string name="deselect" msgid="4297825044827769490">"નાપસંદ કરો"</string> <string name="deselected" msgid="8488133193326208475">"નાપસંદ કર્યું"</string> @@ -62,7 +65,7 @@ <string name="picker_preview" msgid="6257414886055861039">"પ્રીવ્યૂ કરો"</string> <string name="picker_work_profile" msgid="2083221066869141576">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string> <string name="picker_personal_profile" msgid="639484258397758406">"વ્યક્તિગત પ્રોફાઇલ પર સ્વિચ કરો"</string> - <string name="picker_profile_admin_title" msgid="4172022376418293777">"તમારા વ્યવસ્થાપકે સુવિધા બ્લૉક કરી છે"</string> + <string name="picker_profile_admin_title" msgid="4172022376418293777">"તમારા ઍડમિને સુવિધા બ્લૉક કરી છે"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"વ્યક્તિગત ઍપ પરથી ઑફિસનો ડેટા ઍક્સેસ કરવાની પરવાનગી નથી"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"ઑફિસ માટેની ઍપ પરથી વ્યક્તિગત ડેટા ઍક્સેસ કરવાની પરવાનગી નથી"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"ઑફિસ માટેની ઍપ થોભાવવામાં આવી છે"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"તમારું ઇન્ટરનેટ કનેક્શન ચેક કરો અને ફરી પ્રયાસ કરો"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ફરી પ્રયાસ કરો"</string> <string name="not_selected" msgid="2244008151669896758">"પસંદ નહીં કરેલી"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"તમે પસંદ કરેલું મીડિયા તૈયાર કરી રહ્યાં છીએ"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>માંથી <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> તૈયાર"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"બૅકઅપ લીધેલા ફોટા હવે શામેલ કરવામાં આવ્યા છે"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"તમે <xliff:g id="APP_NAME">%1$s</xliff:g> એકાઉન્ટના <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> પરથી ફોટા પસંદ કરી શકો છો"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ઍપ પસંદ કરો"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"એકાઉન્ટ પસંદ કરો"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"એકાઉન્ટ બદલો"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"તમારા બધા ફોટા મેળવવામાં આવી રહ્યાં છે"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>ને આ ઑડિયો ફાઇલમાં ફેરફાર કરવાની મંજૂરી આપીએ?}one{<xliff:g id="APP_NAME_1">^1</xliff:g>ને <xliff:g id="COUNT">^2</xliff:g> ઑડિયો ફાઇલમાં ફેરફાર કરવાની મંજૂરી આપીએ?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>ને <xliff:g id="COUNT">^2</xliff:g> ઑડિયો ફાઇલમાં ફેરફાર કરવાની મંજૂરી આપીએ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ઑડિયો ફાઇલમાં ફેરફાર કરી રહ્યાં છીએ…}one{<xliff:g id="COUNT">^1</xliff:g> ઑડિયો ફાઇલમાં ફેરફાર કરી રહ્યાં છીએ…}other{<xliff:g id="COUNT">^1</xliff:g> ઑડિયો ફાઇલમાં ફેરફાર કરી રહ્યાં છીએ…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>ને આ વીડિયોમાં ફેરફાર કરવાની મંજૂરી આપીએ?}one{<xliff:g id="APP_NAME_1">^1</xliff:g>ને <xliff:g id="COUNT">^2</xliff:g> વીડિયોમાં ફેરફાર કરવાની મંજૂરી આપીએ?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>ને <xliff:g id="COUNT">^2</xliff:g> વીડિયોમાં ફેરફાર કરવાની મંજૂરી આપીએ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"સલામતી સંરક્ષણ"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native Transcode Alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native Transcode Progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"અમુક ફોટા લોડ કરી શકાતા નથી"</string> + <string name="dialog_button_text" msgid="351366485240852280">"સમજાઈ ગયું"</string> </resources> diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index ff9ee11b2..673380955 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"मीडिया"</string> <string name="storage_description" msgid="4081716890357580107">"स्थानीय जगह"</string> <string name="app_label" msgid="9035307001052716210">"मीडिया मेमोरी"</string> - <string name="picker_app_label" msgid="4254039089502164761">"मीडिया"</string> + <string name="picker_app_label" msgid="1195424381053599122">"मीडिया पिकर"</string> <string name="artist_label" msgid="8105600993099120273">"कलाकार"</string> <string name="unknown" msgid="2059049215682829375">"अज्ञात"</string> <string name="root_images" msgid="5861633549189045666">"इमेज"</string> @@ -46,9 +46,12 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"क्लाउड पर मौजूद मीडिया को यहां से ऐक्सेस करें:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"कोई नहीं"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"इस समय क्लाउड मीडिया ऐप्लिकेशन नहीं बदला जा सका."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"मीडिया पिकर"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"मीडिया पिकर"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"मीडिया को सिंक किया जा रहा है…"</string> <string name="add" msgid="2894574044585549298">"जोड़ें"</string> - <string name="deselect" msgid="4297825044827769490">"चुना हुआ हटाएं"</string> - <string name="deselected" msgid="8488133193326208475">"चुना हुआ हटाया गया"</string> + <string name="deselect" msgid="4297825044827769490">"चुने हुए का निशान हटाएं"</string> + <string name="deselected" msgid="8488133193326208475">"चुने हुए का निशान हटाया गया"</string> <string name="select" msgid="2704765470563027689">"चुनें"</string> <string name="selected" msgid="9151797369975828124">"चुना गया"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{ज़्यादा से ज़्यादा <xliff:g id="COUNT_0">^1</xliff:g> आइटम चुनें}one{ज़्यादा से ज़्यादा <xliff:g id="COUNT_1">^1</xliff:g> आइटम चुनें}other{ज़्यादा से ज़्यादा <xliff:g id="COUNT_1">^1</xliff:g> आइटम चुनें}}"</string> @@ -73,7 +76,7 @@ <string name="picker_add_button_multi_select" msgid="4005164092275518399">"(<xliff:g id="COUNT">^1</xliff:g>) जोड़ें"</string> <string name="picker_add_button_multi_select_permissions" msgid="5138751105800138838">"अनुमति दें (<xliff:g id="COUNT">^1</xliff:g>)"</string> <string name="picker_category_camera" msgid="4857367052026843664">"कैमरा"</string> - <string name="picker_category_downloads" msgid="793866660287361900">"डाउनलोड की गई चीज़ें"</string> + <string name="picker_category_downloads" msgid="793866660287361900">"डाउनलोड किए गए आइटम"</string> <string name="picker_category_favorites" msgid="7008495397818966088">"पसंदीदा"</string> <string name="picker_category_screenshots" msgid="7216102327587644284">"स्क्रीनशॉट"</string> <!-- no translation found for picker_category_videos (1478458836380241356) --> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"अपने इंटरनेट कनेक्शन की जांच करें और फिर से कोशिश करें"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"फिर से कोशिश करें"</string> <string name="not_selected" msgid="2244008151669896758">"नहीं चुना गया"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"आपकी चुनी गई मीडिया तैयार की जा रही है"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> में से <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> तैयार हैं"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"बैक अप ली गई फ़ोटो अब जोड़ दी गई हैं"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"आपके पास, <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> वाले <xliff:g id="APP_NAME">%1$s</xliff:g> खाते से फ़ोटो चुनने का विकल्प है"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ऐप्लिकेशन चुनें"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"खाता चुनें"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"खाता बदलें"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"सभी फ़ोटो लोड की जा रही हैं"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{क्या <xliff:g id="APP_NAME_0">^1</xliff:g> को इस ऑडियो फ़ाइल में बदलाव करने की अनुमति देनी है?}one{क्या <xliff:g id="APP_NAME_1">^1</xliff:g> को <xliff:g id="COUNT">^2</xliff:g> ऑडियो फ़ाइल में बदलाव करने की अनुमति देनी है?}other{क्या <xliff:g id="APP_NAME_1">^1</xliff:g> को <xliff:g id="COUNT">^2</xliff:g> ऑडियो फ़ाइलों में बदलाव करने की अनुमति देनी है?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ऑडियो फ़ाइल में बदलाव किया जा रहा है…}one{<xliff:g id="COUNT">^1</xliff:g> ऑडियो फ़ाइल में बदलाव किया जा रहा है…}other{<xliff:g id="COUNT">^1</xliff:g> ऑडियो फ़ाइलों में बदलाव किया जा रहा है…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{क्या <xliff:g id="APP_NAME_0">^1</xliff:g> को इस वीडियो में बदलाव करने की अनुमति देनी है?}one{क्या <xliff:g id="APP_NAME_1">^1</xliff:g> को <xliff:g id="COUNT">^2</xliff:g> वीडियो में बदलाव करने की अनुमति देनी है?}other{क्या <xliff:g id="APP_NAME_1">^1</xliff:g> को <xliff:g id="COUNT">^2</xliff:g> वीडियो में बदलाव करने की अनुमति देनी है?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"सुरक्षा के लिए बचाव"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"नेटिव ट्रांसकोड सूचना"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"नेटिव ट्रांसकोड स्थिति"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"कुछ फ़ोटो लोड नहीं की जा सकीं"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ठीक है"</string> </resources> diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 1a76759d3..b4a060590 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Mediji"</string> <string name="storage_description" msgid="4081716890357580107">"Lokalna pohrana"</string> <string name="app_label" msgid="9035307001052716210">"Pohranjivanje na mediju"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Mediji"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Alat za izbor medija"</string> <string name="artist_label" msgid="8105600993099120273">"Izvođač"</string> <string name="unknown" msgid="2059049215682829375">"Nepoznato"</string> <string name="root_images" msgid="5861633549189045666">"Slike"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Pristupi medijima u oblaku putem"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ništa"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Aplikaciju za medijske sadržaje u oblaku trenutačno nije moguće promijeniti."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Alat za izbor medija"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Alat za izbor medija"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sinkroniziranje medija…"</string> <string name="add" msgid="2894574044585549298">"Dodaj"</string> <string name="deselect" msgid="4297825044827769490">"Poništi odabir"</string> <string name="deselected" msgid="8488133193326208475">"Odabir poništen"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Provjerite internetsku vezu i pokušajte ponovo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Pokušaj ponovo"</string> <string name="not_selected" msgid="2244008151669896758">"nije odabrano"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Priprema odabranih medija"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Spremno: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> od <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Sad su uključene sigurnosno kopirane fotografije"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Možete odabrati aplikacije s računa <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Odaberite aplikaciju"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Odaberite račun"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Promijenite račun"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Dohvaćanje svih vaših fotografija"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_0">^1</xliff:g> da izmijeni tu audiodatoteku?}one{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g> da izmijeni <xliff:g id="COUNT">^2</xliff:g> audiodatoteku?}few{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g> da izmijeni <xliff:g id="COUNT">^2</xliff:g> audiodatoteke?}other{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g> da izmijeni <xliff:g id="COUNT">^2</xliff:g> audiodatoteka?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Mijenjanje audiodatoteke…}one{Mijenjanje <xliff:g id="COUNT">^1</xliff:g> audiodatoteke…}few{Mijenjanje <xliff:g id="COUNT">^1</xliff:g> audiodatoteke…}other{Mijenjanje <xliff:g id="COUNT">^1</xliff:g> audiodatoteka…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_0">^1</xliff:g> da izmijeni taj videozapis?}one{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g> da izmijeni <xliff:g id="COUNT">^2</xliff:g> videozapis?}few{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g> da izmijeni <xliff:g id="COUNT">^2</xliff:g> videozapisa?}other{Želite li dopustiti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g> da izmijeni <xliff:g id="COUNT">^2</xliff:g> videozapisa?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Osiguranje"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Upozorenja nativnog konvertiranja"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Napredak nativnog konvertiranja"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Neke fotografije ne mogu se učitati"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Shvaćam"</string> </resources> diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 47e2fd3cc..e8147b8d1 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Média"</string> <string name="storage_description" msgid="4081716890357580107">"Helyi tárhely"</string> <string name="app_label" msgid="9035307001052716210">"Médiatároló"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Média"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Médiaválasztó"</string> <string name="artist_label" msgid="8105600993099120273">"Előadó"</string> <string name="unknown" msgid="2059049215682829375">"Ismeretlen"</string> <string name="root_images" msgid="5861633549189045666">"Képek"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Hozzáférés a következő szolgáltatásban tárolt felhőbeli médiatartalmakhoz:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Nincs"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Most nem módosítható a felhőbeli médiaalkalmazás."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Médiaválasztó"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Médiaválasztó"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Médiatartalom szinkronizálása…"</string> <string name="add" msgid="2894574044585549298">"Hozzáadás"</string> <string name="deselect" msgid="4297825044827769490">"Jelölés törlése"</string> <string name="deselected" msgid="8488133193326208475">"Kijelölés megszüntetve"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Ellenőrizze internetkapcsolatát, és próbálkozzon újra"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Újra"</string> <string name="not_selected" msgid="2244008151669896758">"nincs kiválasztva"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"A kiválasztott média előkészítése…"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>/<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> kész"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Mostantól rendelkezésre állnak a fotók, amelyekről biztonsági másolat készült"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Kiválaszthat fotókat a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásból (<xliff:g id="USER_ACCOUNT">%2$s</xliff:g>-fiók)"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Válasszon alkalmazást"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Fiók kiválasztása"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Másik fiók választása"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Folyamatban van az összes fotó lekérése"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Engedélyezi a(z) <xliff:g id="APP_NAME_0">^1</xliff:g> számára ennek a hangfájlnak a módosítását?}other{Engedélyezi a(z) <xliff:g id="APP_NAME_1">^1</xliff:g> számára <xliff:g id="COUNT">^2</xliff:g> hangfájl módosítását?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Az audiofájl módosítása folyamatban van…}other{<xliff:g id="COUNT">^1</xliff:g> audiofájl módosítása folyamatban van…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Engedélyezi a(z) <xliff:g id="APP_NAME_0">^1</xliff:g> számára ennek a videónak a módosítását?}other{Engedélyezi a(z) <xliff:g id="APP_NAME_1">^1</xliff:g> számára <xliff:g id="COUNT">^2</xliff:g> videó módosítását?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Biztonsági védelem"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Natív átkódolási értesítések"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Natív átkódolási folyamat"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Egyes fotók nem tölthetők be"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Értem"</string> </resources> diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index ec97ddcc6..1b5bfdb03 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Մեդիա"</string> <string name="storage_description" msgid="4081716890357580107">"Սարքի հիշողություն"</string> <string name="app_label" msgid="9035307001052716210">"Մեդիա կրիչ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Մեդիա"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Մուլտիմեդիա ընտրիչ"</string> <string name="artist_label" msgid="8105600993099120273">"Կատարող"</string> <string name="unknown" msgid="2059049215682829375">"Անհայտ"</string> <string name="root_images" msgid="5861633549189045666">"Պատկերներ"</string> @@ -46,9 +46,12 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Օգտվեք ամպային մեդիա բովանդակությունից հետևյալ մատակարարից՝"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Չկա"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Չհաջողվեց փոխել ամպային մուլտիմեդիա հավելվածը։"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Մուլտիմեդիա ընտրիչ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Մուլտիմեդիա ընտրիչ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Մեդիաֆայլերը համաժամացվում են…"</string> <string name="add" msgid="2894574044585549298">"Ավելացնել"</string> - <string name="deselect" msgid="4297825044827769490">"Ապընտրել"</string> - <string name="deselected" msgid="8488133193326208475">"Ապընտրված"</string> + <string name="deselect" msgid="4297825044827769490">"Չեղարկել ընտրությունը"</string> + <string name="deselected" msgid="8488133193326208475">"Ընտրությունը չեղարկված է"</string> <string name="select" msgid="2704765470563027689">"Ընտրել"</string> <string name="selected" msgid="9151797369975828124">"Ընտրված"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{Ընտրեք մինչև <xliff:g id="COUNT_0">^1</xliff:g> տարր}one{Ընտրեք մինչև <xliff:g id="COUNT_1">^1</xliff:g> տարր}other{Ընտրեք մինչև <xliff:g id="COUNT_1">^1</xliff:g> տարր}}"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Ստուգեք ձեր ինտերնետ կապը և նորից փորձեք"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Նորից փորձել"</string> <string name="not_selected" msgid="2244008151669896758">"ընտրված չէ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Ձեր ընտրած մեդիաֆայլերի նախապատրաստում"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> պատրաստ է"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Պահուստավորված լուսանկարներն այժմ ավելացված են"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Դուք կարող եք լուսանկարներ ընտրել «<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածի <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> հաշվից"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Ընտրել հավելված"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Ընտրել հաշիվը"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Փոխել հաշիվը"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Ձեր բոլոր լուսանկարները բեռնվում են"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Թույլատրե՞լ <xliff:g id="APP_NAME_0">^1</xliff:g> հավելվածին վերականգնել այս աուդիո ֆայլն աղբարկղից}one{Թույլատրե՞լ <xliff:g id="APP_NAME_1">^1</xliff:g> հավելվածին վերականգնել <xliff:g id="COUNT">^2</xliff:g> աուդիո ֆայլ աղբարկղից}other{Թույլատրե՞լ <xliff:g id="APP_NAME_1">^1</xliff:g> հավելվածին վերականգնել <xliff:g id="COUNT">^2</xliff:g> աուդիո ֆայլ աղբարկղից}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Աուդիո ֆայլը փոփոխվում է…}one{<xliff:g id="COUNT">^1</xliff:g> աուդիո ֆայլ փոփոխվում է…}other{<xliff:g id="COUNT">^1</xliff:g> աուդիո ֆայլ փոփոխվում է…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Թույլատրե՞լ <xliff:g id="APP_NAME_0">^1</xliff:g> հավելվածին փոփոխել այս տեսանյութը}one{Թույլատրե՞լ <xliff:g id="APP_NAME_1">^1</xliff:g> հավելվածին փոփոխել <xliff:g id="COUNT">^2</xliff:g> տեսանյութ}other{Թույլատրե՞լ <xliff:g id="APP_NAME_1">^1</xliff:g> հավելվածին փոփոխել <xliff:g id="COUNT">^2</xliff:g> տեսանյութ}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Անվտանգության պաշտպանություն"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Տրանսկոդավորման մասին հիմնական ծանուցումներ"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Տրանսկոդավորման հիմնական գործընթաց"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Չհաջողվեց բեռնել որոշ լուսանկարներ"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Եղավ"</string> </resources> diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 4043b13a2..5ae9ebcfa 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Penyimpanan lokal"</string> <string name="app_label" msgid="9035307001052716210">"Penyimpanan Media"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Pemilih media"</string> <string name="artist_label" msgid="8105600993099120273">"Artis"</string> <string name="unknown" msgid="2059049215682829375">"Tidak diketahui"</string> <string name="root_images" msgid="5861633549189045666">"Gambar"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Akses media cloud dari"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Tidak ada"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Saat ini tidak bisa mengubah aplikasi media cloud."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Pemilih media"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Pemilih media"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Menyinkronkan media…"</string> <string name="add" msgid="2894574044585549298">"Tambahkan"</string> <string name="deselect" msgid="4297825044827769490">"Batalkan pilihan"</string> <string name="deselected" msgid="8488133193326208475">"Batal dipilih"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Periksa koneksi internet Anda, lalu coba lagi"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Coba lagi"</string> <string name="not_selected" msgid="2244008151669896758">"tidak dipilih"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Menyiapkan media yang dipilih"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> dari <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> siap"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Foto yang dicadangkan kini disertakan"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Anda dapat memilih foto dari akun <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Pilih aplikasi"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Pilih akun"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Ubah akun"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Mengambil semua foto Anda"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Izinkan <xliff:g id="APP_NAME_0">^1</xliff:g> mengubah file audio ini?}other{Izinkan <xliff:g id="APP_NAME_1">^1</xliff:g> mengubah <xliff:g id="COUNT">^2</xliff:g> file audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Mengubah file audio …}other{Mengubah <xliff:g id="COUNT">^1</xliff:g> file audio …}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Izinkan <xliff:g id="APP_NAME_0">^1</xliff:g> mengubah video ini?}other{Izinkan <xliff:g id="APP_NAME_1">^1</xliff:g> mengubah <xliff:g id="COUNT">^2</xliff:g> video?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Perlindungan keselamatan"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Peringatan Transcoding Native"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progres Transcoding Native"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Tidak dapat memuat beberapa Foto"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Oke"</string> </resources> diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 9f923f27c..c8886c207 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Margmiðlun"</string> <string name="storage_description" msgid="4081716890357580107">"Staðbundin vistun"</string> <string name="app_label" msgid="9035307001052716210">"Efnisgeymsla"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Efni"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Efnisval"</string> <string name="artist_label" msgid="8105600993099120273">"Flytjandi"</string> <string name="unknown" msgid="2059049215682829375">"Óþekkt"</string> <string name="root_images" msgid="5861633549189045666">"Myndir"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Opna skýjaefni frá"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ekkert"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Ekki tókst að breyta efnisforriti í skýi."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Efnisval"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Efnisval"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Samstillir efni…"</string> <string name="add" msgid="2894574044585549298">"Bæta við"</string> <string name="deselect" msgid="4297825044827769490">"Afvelja"</string> <string name="deselected" msgid="8488133193326208475">"Afvalið"</string> @@ -61,7 +64,7 @@ <string name="picker_albums" msgid="4822511902115299142">"Albúm"</string> <string name="picker_preview" msgid="6257414886055861039">"Forskoða"</string> <string name="picker_work_profile" msgid="2083221066869141576">"Skipta yfir í vinnusnið"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Skipta yfir í eigið snið"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Skipta yfir í einkasnið"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Útilokað af kerfisstjóra"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Óheimilt er að opna vinnugögn í forriti til einkanota"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Óheimilt er að opna einkagögn í vinnuforriti"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Athugaðu nettenginguna og reyndu aftur"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Reyna aftur"</string> <string name="not_selected" msgid="2244008151669896758">"ekki valið"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Undirbýr valið efni"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> af <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> til reiðu"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Afritaðar myndir eru nú hafðar með"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Þú getur valið myndir af reikningnum <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> í: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Velja forrit"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Veldu reikning"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Skipta um reikning"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Sækir allar myndirnar þínar"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Leyfa <xliff:g id="APP_NAME_0">^1</xliff:g> að breyta þessari hljóðskrá?}one{Leyfa <xliff:g id="APP_NAME_1">^1</xliff:g> að breyta <xliff:g id="COUNT">^2</xliff:g> hljóðskrá?}other{Leyfa <xliff:g id="APP_NAME_1">^1</xliff:g> að breyta <xliff:g id="COUNT">^2</xliff:g> hljóðskrám?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Breytir hljóðskrá…}one{Breytir <xliff:g id="COUNT">^1</xliff:g> hljóðskrá…}other{Breytir <xliff:g id="COUNT">^1</xliff:g> hljóðskrám…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Leyfa <xliff:g id="APP_NAME_0">^1</xliff:g> að breyta þessu myndskeiði?}one{Leyfa <xliff:g id="APP_NAME_1">^1</xliff:g> að breyta <xliff:g id="COUNT">^2</xliff:g> myndskeiði?}other{Leyfa <xliff:g id="APP_NAME_1">^1</xliff:g> að breyta <xliff:g id="COUNT">^2</xliff:g> myndskeiðum?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Öryggisbúnaður"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Viðvaranir fyrir sérforritaðar umkóðanir"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Sérforritað umkóðunarferli"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Ekki tekst að hlaða sumum myndum"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Ég skil"</string> </resources> diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 19d628756..04408b614 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Supporti multimediali"</string> <string name="storage_description" msgid="4081716890357580107">"Archiviazione locale"</string> <string name="app_label" msgid="9035307001052716210">"Media Storage"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Contenuti multimediali"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Selettore media"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Sconosciuto"</string> <string name="root_images" msgid="5861633549189045666">"Immagini"</string> @@ -42,10 +42,13 @@ <string name="picker_settings" msgid="6443463167344790260">"App multimediale cloud"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"App multimediale cloud"</string> <string name="picker_settings_title" msgid="5647700706470673258">"App multimediale con funzionalità cloud"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Accedi ai tuoi contenuti multimediali cloud quando un\'app o un sito web ti chiede di selezionare foto o video"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Accedi ai tuoi contenuti multimediali sul cloud quando un\'app o un sito web ti chiede di selezionare foto o video"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Accedi ai contenuti multimediali sul cloud da"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Nessuna"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Ora è impossibile cambiare app multimediale cloud."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Selettore media"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Selettore media"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sincronizzazione dei media in corso…"</string> <string name="add" msgid="2894574044585549298">"Aggiungi"</string> <string name="deselect" msgid="4297825044827769490">"Deseleziona"</string> <string name="deselected" msgid="8488133193326208475">"Deselezionato"</string> @@ -67,7 +70,7 @@ <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Non è consentito accedere ai dati personali da un\'app di lavoro"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"Le app di lavoro sono in pausa"</string> <string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"Per aprire le foto relative al lavoro, attiva le app di lavoro e riprova"</string> - <string name="picker_privacy_message" msgid="9132700451027116817">"Questa app può accedere soltanto alle foto selezionate da te"</string> + <string name="picker_privacy_message" msgid="9132700451027116817">"Questa app può accedere soltanto alle foto che selezioni"</string> <string name="picker_header_permissions" msgid="675872774407768495">"Seleziona le foto e i video a cui può accedere questa app"</string> <string name="picker_album_item_count" msgid="4420723302534177596">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> elemento}many{<xliff:g id="COUNT_1">^1</xliff:g> elementi}other{<xliff:g id="COUNT_1">^1</xliff:g> elementi}}"</string> <string name="picker_add_button_multi_select" msgid="4005164092275518399">"Aggiungi (<xliff:g id="COUNT">^1</xliff:g>)"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Controlla la connessione a Internet e riprova"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Riprova"</string> <string name="not_selected" msgid="2244008151669896758">"Elemento non selezionato"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparazione dei contenuti multimediali selezionati in corso…"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> su <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> pronti"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Ora sono incluse le foto di cui hai eseguito il backup"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Puoi selezionare foto dall\'account <xliff:g id="APP_NAME">%1$s</xliff:g> di <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Puoi selezionare foto dall\'account <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> nell\'app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"Account <xliff:g id="APP_NAME">%1$s</xliff:g> aggiornato"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Ora le foto di <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> sono incluse qui"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"Scegli un\'app multimediale con funzionalità cloud"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Scegli app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Scegli account"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Cambia account"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Recupero di tutte le tue foto in corso…"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Consentire all\'app <xliff:g id="APP_NAME_0">^1</xliff:g> di modificare questo file audio?}many{Consentire all\'app <xliff:g id="APP_NAME_1">^1</xliff:g> di modificare <xliff:g id="COUNT">^2</xliff:g> file audio?}other{Consentire all\'app <xliff:g id="APP_NAME_1">^1</xliff:g> di modificare <xliff:g id="COUNT">^2</xliff:g> file audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modifica del file audio in corso…}many{Modifica di <xliff:g id="COUNT">^1</xliff:g> file audio in corso…}other{Modifica di <xliff:g id="COUNT">^1</xliff:g> file audio in corso…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Consentire all\'app <xliff:g id="APP_NAME_0">^1</xliff:g> di modificare questo video?}many{Consentire all\'app <xliff:g id="APP_NAME_1">^1</xliff:g> di modificare <xliff:g id="COUNT">^2</xliff:g> video?}other{Consentire all\'app <xliff:g id="APP_NAME_1">^1</xliff:g> di modificare <xliff:g id="COUNT">^2</xliff:g> video?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protezione di sicurezza"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Avvisi di transcodifica nativa"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Avanzamento di transcodifica nativa"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Impossibile caricare alcune foto"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index a8ddffd52..4bd3784eb 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"מדיה"</string> <string name="storage_description" msgid="4081716890357580107">"אחסון מקומי"</string> <string name="app_label" msgid="9035307001052716210">"אחסון מדיה"</string> - <string name="picker_app_label" msgid="4254039089502164761">"מדיה"</string> + <string name="picker_app_label" msgid="1195424381053599122">"הכלי לבחירת מדיה"</string> <string name="artist_label" msgid="8105600993099120273">"אומן"</string> <string name="unknown" msgid="2059049215682829375">"לא ידוע"</string> <string name="root_images" msgid="5861633549189045666">"תמונות"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"גישה למדיה בענן מתוך"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ללא"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"לא ניתן להחליף את אפליקציית המדיה בענן כרגע."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"הכלי לבחירת מדיה"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"הכלי לבחירת מדיה"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"המדיה בתהליך סנכרון…"</string> <string name="add" msgid="2894574044585549298">"הוספה"</string> <string name="deselect" msgid="4297825044827769490">"ביטול הבחירה"</string> <string name="deselected" msgid="8488133193326208475">"הבחירה בוטלה"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"מומלץ לבדוק את החיבור לאינטרנט ולנסות שוב"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ניסיון נוסף"</string> <string name="not_selected" msgid="2244008151669896758">"לא נבחר"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"המדיה שבחרת בתהליך הכנה"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> מוכנים"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"התמונות שעברו גיבוי נכללות עכשיו"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"ניתן לבחור תמונות מחשבון <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> באפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"בחירת אפליקציה"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"בחירת חשבון"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"החלפת חשבון"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"איסוף התמונות מתבצע"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{לאפשר לאפליקציה <xliff:g id="APP_NAME_0">^1</xliff:g> לשנות את קובץ האודיו הזה?}one{לאפשר לאפליקציה <xliff:g id="APP_NAME_1">^1</xliff:g> לשנות <xliff:g id="COUNT">^2</xliff:g> קובצי אודיו?}two{לאפשר לאפליקציה <xliff:g id="APP_NAME_1">^1</xliff:g> לשנות <xliff:g id="COUNT">^2</xliff:g> קובצי אודיו?}other{לאפשר לאפליקציה <xliff:g id="APP_NAME_1">^1</xliff:g> לשנות <xliff:g id="COUNT">^2</xliff:g> קובצי אודיו?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{מתבצע שינוי בקובץ האודיו…}one{מתבצע שינוי ב-<xliff:g id="COUNT">^1</xliff:g> קובצי אודיו…}two{מתבצע שינוי ב-<xliff:g id="COUNT">^1</xliff:g> קובצי אודיו…}other{מתבצע שינוי ב-<xliff:g id="COUNT">^1</xliff:g> קובצי אודיו…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{לאפשר לאפליקציה <xliff:g id="APP_NAME_0">^1</xliff:g> לשנות את הסרטון הזה?}one{לאפשר לאפליקציה <xliff:g id="APP_NAME_1">^1</xliff:g> לשנות <xliff:g id="COUNT">^2</xliff:g> סרטונים?}two{לאפשר לאפליקציה <xliff:g id="APP_NAME_1">^1</xliff:g> לשנות <xliff:g id="COUNT">^2</xliff:g> סרטונים?}other{לאפשר לאפליקציה <xliff:g id="APP_NAME_1">^1</xliff:g> לשנות <xliff:g id="COUNT">^2</xliff:g> סרטונים?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"הגנה על בטיחות"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"התראות של המרת קידוד מקורית"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"התקדמות של המרת קידוד מקורית"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"לא ניתן לטעון תמונות מסוימות"</string> + <string name="dialog_button_text" msgid="351366485240852280">"הבנתי"</string> </resources> diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 5b0bef4de..41b649ce6 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"メディア"</string> <string name="storage_description" msgid="4081716890357580107">"ローカル ストレージ"</string> <string name="app_label" msgid="9035307001052716210">"メディア ストレージ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"メディア"</string> + <string name="picker_app_label" msgid="1195424381053599122">"メディアの選択"</string> <string name="artist_label" msgid="8105600993099120273">"アーティスト"</string> <string name="unknown" msgid="2059049215682829375">"不明"</string> <string name="root_images" msgid="5861633549189045666">"画像"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"クラウド メディアへのアクセス元"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"なし"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"クラウド メディアアプリを変更できませんでした。"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"メディアの選択"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"メディアの選択"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"メディアを同期しています…"</string> <string name="add" msgid="2894574044585549298">"追加"</string> <string name="deselect" msgid="4297825044827769490">"選択を解除"</string> <string name="deselected" msgid="8488133193326208475">"選択解除済み"</string> @@ -63,7 +66,7 @@ <string name="picker_work_profile" msgid="2083221066869141576">"仕事用に切り替える"</string> <string name="picker_personal_profile" msgid="639484258397758406">"個人用に切り替える"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"管理者によりブロックされています"</string> - <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"個人用アプリから仕事用データにアクセスすることは認められていません"</string> + <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"個人用アプリから仕事用データにアクセスすることは許可されていません"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"仕事用アプリから個人データにアクセスすることは認められていません"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"仕事用アプリ一時停止中"</string> <string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"仕事用の写真を開くには、仕事用アプリを有効にしてからもう一度試してください。"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"インターネット接続を確認してもう一度お試しください"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"再試行"</string> <string name="not_selected" msgid="2244008151669896758">"未選択"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"選択したメディアの準備をする"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> 件準備完了"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"バックアップした写真が追加されました"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> のアカウント <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> の写真を選択できます"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"アプリを選択"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"アカウントを選択"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"アカウントを変更"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"すべての写真を取得しています"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{この音声ファイルの変更を <xliff:g id="APP_NAME_0">^1</xliff:g> に許可しますか?}other{<xliff:g id="COUNT">^2</xliff:g> 件の音声ファイルの変更を <xliff:g id="APP_NAME_1">^1</xliff:g> に許可しますか?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{音声ファイルを変更しています…}other{<xliff:g id="COUNT">^1</xliff:g> 件の音声ファイルを変更しています…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{この動画の変更を <xliff:g id="APP_NAME_0">^1</xliff:g> に許可しますか?}other{<xliff:g id="COUNT">^2</xliff:g> 本の動画の変更を <xliff:g id="APP_NAME_1">^1</xliff:g> に許可しますか?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"安全保護"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"ネイティブ コード変換アラート"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"ネイティブ コード変換進行状況"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"読み込めなかった写真があります"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index ecb247611..1f1974e53 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"მედია"</string> <string name="storage_description" msgid="4081716890357580107">"ადგილობრივი მეხსიერება"</string> <string name="app_label" msgid="9035307001052716210">"მედიის საცავი"</string> - <string name="picker_app_label" msgid="4254039089502164761">"მედია"</string> + <string name="picker_app_label" msgid="1195424381053599122">"მედიის ამომრჩევი"</string> <string name="artist_label" msgid="8105600993099120273">"შემსრულებელი"</string> <string name="unknown" msgid="2059049215682829375">"უცნობი"</string> <string name="root_images" msgid="5861633549189045666">"სურათები"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ღრუბლოვან მედიაზე წვდომა აქედან:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"არცერთი"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"ღრუბლური მედია აპის შეცვლა ამჯერად ვერ ხერხდება."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"მედიის ამომრჩევი"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"მედიის ამომრჩევი"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"მიმდინარეობს მედიის სინქრონიზაცია…"</string> <string name="add" msgid="2894574044585549298">"დამატება"</string> <string name="deselect" msgid="4297825044827769490">"არჩევის გაუქმება"</string> <string name="deselected" msgid="8488133193326208475">"არჩევა გაუქმებულია"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"შეამოწმეთ ინტერნეტთან კავშირი და სცადეთ ხელახლა"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ცდა"</string> <string name="not_selected" msgid="2244008151669896758">"არ არის არჩეული"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"მიმდინარეობს თქვენ მიერ არჩეული მედიის მომზადება"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> სულ <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>-დან მზადაა"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ფოტოების სარეზერვო ასლები ახლა განთავსებულია"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"უკვე ფოტოების სარეზერვო ასლების ჩათვლით"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"შეგიძლიათ აირჩიოთ ფოტოები <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ანგარიშიდან <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g> ანგარიში განახლებულია"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"<xliff:g id="USER_ACCOUNT">%1$s</xliff:g>-ის ფოტოები ახლა აქ არის განთავსებული"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"აპის არჩევა"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"აირჩიეთ ანგარიში"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ანგარიშის შეცვლა"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"თქვენი ყველა ფოტოს მიღება"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{აძლევთ უფლებას <xliff:g id="APP_NAME_0">^1</xliff:g>-ს, შეცვალოს ეს აუდიოფაილი?}other{აძლევთ უფლებას <xliff:g id="APP_NAME_1">^1</xliff:g>-ს, შეცვალოს <xliff:g id="COUNT">^2</xliff:g> აუდიოფაილი?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{მიმდინარეობს აუდიოფაილის მოდიფიკაცია…}other{მიმდინარეობს <xliff:g id="COUNT">^1</xliff:g> აუდიოფაილის მოდიფიკაცია…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{აძლევთ უფლებას <xliff:g id="APP_NAME_0">^1</xliff:g>-ს, შეცვალოს ეს ვიდეო?}other{აძლევთ უფლებას <xliff:g id="APP_NAME_1">^1</xliff:g>-ს, შეცვალოს <xliff:g id="COUNT">^2</xliff:g> ვიდეო?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"უსაფრთხოების დაცვა"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"ტრანსკოდირების ადგილობრივი გაფრთხილება"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"ტრანსკოდირების ადგილობრივი პროგრესი"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"ზოგიერთი ფოტოს ჩატვირთვა ვერ ხერხდება"</string> + <string name="dialog_button_text" msgid="351366485240852280">"გასაგებია"</string> </resources> diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 245978fb4..081402708 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Мультимeдиа"</string> <string name="storage_description" msgid="4081716890357580107">"Жергілікті жад"</string> <string name="app_label" msgid="9035307001052716210">"Мультимедиа қоймасы"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Meдиа"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Meдиафайл таңдағыш"</string> <string name="artist_label" msgid="8105600993099120273">"Орындаушы"</string> <string name="unknown" msgid="2059049215682829375">"Белгісіз"</string> <string name="root_images" msgid="5861633549189045666">"Кескіндер"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Бұлттық мультимедиа қолданбасына келесі жерден кіріңіз:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Жоқ"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Бұлттық мультимедиа қолданбасы өзгертілмейді."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Meдиафайл таңдағыш"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Meдиафайл таңдағыш"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Медиафайл синхрондалып жатыр…"</string> <string name="add" msgid="2894574044585549298">"Қосу"</string> <string name="deselect" msgid="4297825044827769490">"Таңдамау"</string> <string name="deselected" msgid="8488133193326208475">"Таңдау алынған"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Интернет байланысын тексеріп, әрекетті қайталаңыз."</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Қайталау"</string> <string name="not_selected" msgid="2244008151669896758">"таңдалмаған"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Таңдалған мультимедиа әзірленіп жатыр"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> дайын"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Сақтық көшірмесі жасалған фотосуреттер қосылды"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Фотосуреттерді <xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасының <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> аккаунтынан таңдай аласыз."</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Қолданба таңдау"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Аккаунт таңдау"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Аккаунтты өзгерту"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Барлық сурет алынып жатыр."</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> қолданбасына осы аудиофайлды өзгертуге рұқсат етілсін бе?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> қолданбасына <xliff:g id="COUNT">^2</xliff:g> аудиофайлды өзгертуге рұқсат етілсін бе?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Аудиофайл өзгертілуде…}other{<xliff:g id="COUNT">^1</xliff:g> аудиофайл өзгертілуде…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> қолданбасына осы бейнені өзгертуге рұқсат етілсін бе?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> қолданбасына <xliff:g id="COUNT">^2</xliff:g> бейнені өзгертуге рұқсат етілсін бе?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Қауіпсіздікті қорғау"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Түбірлік транскодтау туралы хабарландырулар"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Түбірлік транскодтау прогресі"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Кейбір фотосуреттерді жүктеу мүмкін емес"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Түсінікті"</string> </resources> diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index 17480e893..39e2f828d 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"មេឌៀ"</string> <string name="storage_description" msgid="4081716890357580107">"ទំហំផ្ទុកមូលដ្ឋាន"</string> <string name="app_label" msgid="9035307001052716210">"ទំហំផ្ទុកមេឌៀ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"មេឌៀ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"មុខងារជ្រើសរើសមេឌៀ"</string> <string name="artist_label" msgid="8105600993099120273">"សិល្បករ"</string> <string name="unknown" msgid="2059049215682829375">"មិនស្គាល់"</string> <string name="root_images" msgid="5861633549189045666">"រូបភាព"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ចូលប្រើប្រាស់មេឌៀលើពពកពី"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"គ្មាន"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"មិនអាចប្ដូរកម្មវិធីមេឌៀពពកនៅពេលនេះបានទេ។"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"មុខងារជ្រើសរើសមេឌៀ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"មុខងារជ្រើសរើសមេឌៀ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"កំពុងធ្វើសមកាលកម្មមេឌៀ…"</string> <string name="add" msgid="2894574044585549298">"បញ្ចូល"</string> <string name="deselect" msgid="4297825044827769490">"ដកការជ្រើសរើស"</string> <string name="deselected" msgid="8488133193326208475">"បានដកការជ្រើសរើស"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ពិនិត្យការតភ្ជាប់អ៊ីនធឺណិតរបស់អ្នក រួចព្យាយាមម្ដងទៀត"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ព្យាយាមម្ដងទៀត"</string> <string name="not_selected" msgid="2244008151669896758">"មិនបានជ្រើសរើសទេ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"កំពុងរៀបចំមេឌៀដែលអ្នកបានជ្រើសរើស"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> រួចរាល់ហើយ"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ឥឡូវនេះមានរួមបញ្ចូលរូបថតដែលបានបម្រុងទុក"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"អ្នកអាចជ្រើសរើសរូបថតពីគណនី <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> របស់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"អ្នកអាចជ្រើសរើសរូបថតពីគណនី <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"បានធ្វើបច្ចុប្បន្នភាពគណនី <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"ឥឡូវនេះ រូបថតពី <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> ត្រូវបានរួមបញ្ចូលនៅទីនេះ"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"ជ្រើសរើសកម្មវិធីមេឌៀលើពពក"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ជ្រើសរើសកម្មវិធី"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"ជ្រើសរើសគណនី"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ប្ដូរគណនី"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"កំពុងផ្ទុករូបថតទាំងអស់របស់អ្នក"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{អនុញ្ញាតឱ្យ <xliff:g id="APP_NAME_0">^1</xliff:g> កែឯកសារសំឡេងនេះឬ?}other{អនុញ្ញាតឱ្យ <xliff:g id="APP_NAME_1">^1</xliff:g> កែឯកសារសំឡេង <xliff:g id="COUNT">^2</xliff:g> ឬ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{កំពុងកែឯកសារសំឡេង…}other{កំពុងកែឯកសារសំឡេង <xliff:g id="COUNT">^1</xliff:g>…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{អនុញ្ញាតឱ្យ <xliff:g id="APP_NAME_0">^1</xliff:g> កែវីដេអូនេះឬ?}other{អនុញ្ញាតឱ្យ <xliff:g id="APP_NAME_1">^1</xliff:g> កែវីដេអូ <xliff:g id="COUNT">^2</xliff:g> ឬ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"ការការពារសុវត្ថិភាព"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"ការជូនដំណឹងអំពីការបំប្លែងកូដដើម"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"ដំណើរវិវឌ្ឍនៃការបំប្លែងកូដដើម"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"មិនអាចផ្ទុករូបថតមួយចំនួនបានទេ"</string> + <string name="dialog_button_text" msgid="351366485240852280">"យល់ហើយ"</string> </resources> diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 2663f7bb2..d83ff1a95 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"ಮಾಧ್ಯಮ"</string> <string name="storage_description" msgid="4081716890357580107">"ಸ್ಥಳೀಯ ಸಂಗ್ರಹಣೆ"</string> <string name="app_label" msgid="9035307001052716210">"ಮಾಧ್ಯಮ ಸಂಗ್ರಹಣೆ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"ಮಾಧ್ಯಮ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"ಮಾಧ್ಯಮ ಪಿಕರ್"</string> <string name="artist_label" msgid="8105600993099120273">"ಕಲಾವಿದರು"</string> <string name="unknown" msgid="2059049215682829375">"ಅಪರಿಚಿತ"</string> <string name="root_images" msgid="5861633549189045666">"ಚಿತ್ರಗಳು"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ಇದರಿಂದ ಕ್ಲೌಡ್ ಮಾಧ್ಯಮವನ್ನು ಪ್ರವೇಶಿಸಿ"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ಯಾವುದೂ ಅಲ್ಲ"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"ಇದೀಗ ಕ್ಲೌಡ್ ಮೀಡಿಯಾ ಆ್ಯಪ್ ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"ಮಾಧ್ಯಮ ಪಿಕರ್"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"ಮಾಧ್ಯಮ ಪಿಕರ್"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"ಮಾಧ್ಯಮವನ್ನು ಸಿಂಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string> <string name="add" msgid="2894574044585549298">"ಸೇರಿಸಿ"</string> <string name="deselect" msgid="4297825044827769490">"ಆಯ್ಕೆ ರದ್ದುಮಾಡಿ"</string> <string name="deselected" msgid="8488133193326208475">"ಆಯ್ಕೆ ರದ್ದುಮಾಡಲಾಗಿದೆ"</string> @@ -60,16 +63,16 @@ <string name="picker_photos" msgid="7415035516411087392">"ಫೋಟೋಗಳು"</string> <string name="picker_albums" msgid="4822511902115299142">"ಆಲ್ಬಮ್ಗಳು"</string> <string name="picker_preview" msgid="6257414886055861039">"ಪೂರ್ವವೀಕ್ಷಣೆ"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"ಕೆಲಸಕ್ಕೆ ಬದಲಿಸಿ"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"ವೈಯಕ್ತಿಕಕ್ಕೆ ಬದಲಿಸಿ"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ಗೆ ಬದಲಿಸಿ"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್ಗೆ ಬದಲಿಸಿ"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿರ್ಬಂಧಿಸಿದ್ದಾರೆ"</string> - <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"ವೈಯಕ್ತಿಕ ಆ್ಯಪ್ ಮೂಲಕ ಅಧಿಕೃತ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string> + <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"ವೈಯಕ್ತಿಕ ಆ್ಯಪ್ನಿಂದ ಉದ್ಯೋಗದ ಡೇಟಾವನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ ಮೂಲಕ ಅಧಿಕೃತ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"ಕೆಲಸದ ಫೋಟೋಗಳನ್ನು ತೆರೆಯಲು, ನಿಮ್ಮ ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> - <string name="picker_privacy_message" msgid="9132700451027116817">"ಈ ಆ್ಯಪ್ ನೀವು ಆಯ್ಕೆಮಾಡಿದ ಫೋಟೋಗಳನ್ನು ಮಾತ್ರ ಪ್ರವೇಶಿಸಬಹುದು"</string> + <string name="picker_privacy_message" msgid="9132700451027116817">"ಈ ಆ್ಯಪ್ ನೀವು ಆಯ್ಕೆಮಾಡಿದ ಫೋಟೋಗಳನ್ನು ಮಾತ್ರ ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು"</string> <string name="picker_header_permissions" msgid="675872774407768495">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ನೀವು ಅನುಮತಿಸುವ ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> - <string name="picker_album_item_count" msgid="4420723302534177596">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g>ಐಟಂ}one{<xliff:g id="COUNT_1">^1</xliff:g> ಐಟಂಗಳು}other{<xliff:g id="COUNT_1">^1</xliff:g> ಐಟಂಗಳು}}"</string> + <string name="picker_album_item_count" msgid="4420723302534177596">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> ಐಟಂ}one{<xliff:g id="COUNT_1">^1</xliff:g> ಐಟಂಗಳು}other{<xliff:g id="COUNT_1">^1</xliff:g> ಐಟಂಗಳು}}"</string> <string name="picker_add_button_multi_select" msgid="4005164092275518399">"ಸೇರಿಸಿ (<xliff:g id="COUNT">^1</xliff:g>)"</string> <string name="picker_add_button_multi_select_permissions" msgid="5138751105800138838">"(<xliff:g id="COUNT">^1</xliff:g>) ಅನುಮತಿಸಿ"</string> <string name="picker_category_camera" msgid="4857367052026843664">"ಕ್ಯಾಮರಾ"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ನಿಮ್ಮ ಇಂಟರ್ನೆಟ್ ಕನೆಕ್ಷನ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ಮರುಪ್ರಯತ್ನಿಸಿ"</string> <string name="not_selected" msgid="2244008151669896758">"ಆಯ್ಕೆಮಾಡಲಾಗಿಲ್ಲ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"ನಿಮ್ಮ ಆಯ್ಕೆಮಾಡಿದ ಮೀಡಿಯಾವನ್ನು ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> ಸಿದ್ಧವಾಗಿವೆ"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ಬ್ಯಾಕಪ್ ಮಾಡಲಾದ ಫೋಟೋಗಳನ್ನು ಈಗ ಸೇರಿಸಲಾಗಿದೆ"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಖಾತೆಯ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> ನಲ್ಲಿರುವ ಫೋಟೋಗಳನ್ನು ನೀವು ಆಯ್ಕೆಮಾಡಬಹುದು"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ಆ್ಯಪ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"ಖಾತೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ಖಾತೆಯನ್ನು ಬದಲಾಯಿಸಿ"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"ನಿಮ್ಮ ಎಲ್ಲಾ ಫೋಟೋಗಳನ್ನು ಪಡೆಯಲಾಗುತ್ತಿದೆ"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{ಈ ಆಡಿಯೋ ಫೈಲ್ ಅನ್ನು ಮಾರ್ಪಡಿಸಲು <xliff:g id="APP_NAME_0">^1</xliff:g> ಗೆ ಅನುಮತಿ ನೀಡಬೇಕೇ?}one{ಈ <xliff:g id="COUNT">^2</xliff:g> ಆಡಿಯೋ ಫೈಲ್ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು <xliff:g id="APP_NAME_1">^1</xliff:g> ಗೆ ಅನುಮತಿ ನೀಡಬೇಕೇ?}other{ಈ <xliff:g id="COUNT">^2</xliff:g> ಆಡಿಯೋ ಫೈಲ್ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು <xliff:g id="APP_NAME_1">^1</xliff:g> ಗೆ ಅನುಮತಿ ನೀಡಬೇಕೇ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ಆಡಿಯೋ ಫೈಲ್ ಅನ್ನು ಮಾರ್ಪಡಿಸಲಾಗುತ್ತಿದೆ…}one{<xliff:g id="COUNT">^1</xliff:g> ಆಡಿಯೋ ಫೈಲ್ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲಾಗುತ್ತಿದೆ…}other{<xliff:g id="COUNT">^1</xliff:g> ಆಡಿಯೋ ಫೈಲ್ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲಾಗುತ್ತಿದೆ…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{ಈ ವೀಡಿಯೊವನ್ನು ಮಾರ್ಪಡಿಸಲು <xliff:g id="APP_NAME_0">^1</xliff:g> ಗೆ ಅನುಮತಿ ನೀಡಬೇಕೇ?}one{ಈ <xliff:g id="COUNT">^2</xliff:g> ವೀಡಿಯೊಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು <xliff:g id="APP_NAME_1">^1</xliff:g> ಗೆ ಅನುಮತಿ ನೀಡಬೇಕೇ?}other{ಈ <xliff:g id="COUNT">^2</xliff:g> ವೀಡಿಯೊಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು <xliff:g id="APP_NAME_1">^1</xliff:g> ಗೆ ಅನುಮತಿ ನೀಡಬೇಕೇ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"ಭದ್ರತಾ ರಕ್ಷಣೆ"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"ನೇಟಿವ್ ಟ್ರಾನ್ಸ್ಕೋಡ್ ಅಲರ್ಟ್ಗಳು"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"ನೇಟಿವ್ ಟ್ರಾನ್ಸ್ಕೋಡ್ ಪ್ರಗತಿ"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"ಕೆಲವು ಫೋಟೋಗಳನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ಅರ್ಥವಾಯಿತು"</string> </resources> diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 9b867da5c..0d31cd73c 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"미디어"</string> <string name="storage_description" msgid="4081716890357580107">"로컬 저장소"</string> <string name="app_label" msgid="9035307001052716210">"미디어 저장소"</string> - <string name="picker_app_label" msgid="4254039089502164761">"미디어"</string> + <string name="picker_app_label" msgid="1195424381053599122">"미디어 선택 도구"</string> <string name="artist_label" msgid="8105600993099120273">"아티스트"</string> <string name="unknown" msgid="2059049215682829375">"알 수 없음"</string> <string name="root_images" msgid="5861633549189045666">"이미지"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"클라우드 미디어 액세스 위치"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"없음"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"현재 클라우드 미디어 앱을 변경할 수 없습니다."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"미디어 선택 도구"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"미디어 선택 도구"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"미디어 동기화 중…"</string> <string name="add" msgid="2894574044585549298">"추가"</string> <string name="deselect" msgid="4297825044827769490">"선택 해제"</string> <string name="deselected" msgid="8488133193326208475">"선택 해제됨"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"사진"</string> <string name="picker_albums" msgid="4822511902115299142">"앨범"</string> <string name="picker_preview" msgid="6257414886055861039">"미리보기"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"직장으로 전환"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"개인으로 전환"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"직장 프로필로 전환"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"개인 프로필로 전환"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"관리자가 차단함"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"개인 앱에서는 업무 데이터에 액세스할 수 없습니다."</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"직장 앱에서는 개인 데이터에 액세스할 수 없습니다."</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"인터넷 연결 상태를 확인하고 다시 시도해 주세요."</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"다시 시도"</string> <string name="not_selected" msgid="2244008151669896758">"선택되지 않음"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"선택한 미디어를 준비하는 중"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>개 준비됨"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"이제 백업된 사진이 포함됨"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> 계정(<xliff:g id="USER_ACCOUNT">%2$s</xliff:g>)에서 사진을 선택할 수 있습니다."</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"앱 선택"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"계정 선택"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"계정 변경"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"모든 사진 가져오는 중"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>에서 이 오디오 파일을 수정하도록 허용하시겠습니까?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>에서 오디오 파일 <xliff:g id="COUNT">^2</xliff:g>개를 수정하도록 허용하시겠습니까?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{오디오 파일 수정 중…}other{오디오 파일 <xliff:g id="COUNT">^1</xliff:g>개 수정 중…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>에서 이 동영상을 수정하도록 허용하시겠습니까?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>에서 동영상 <xliff:g id="COUNT">^2</xliff:g>개를 수정하도록 허용하시겠습니까?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"안전 보안"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"네이티브 트랜스코드 알림"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"네이티브 트랜스코드 진행 상황"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"일부 사진을 로드할 수 없음"</string> + <string name="dialog_button_text" msgid="351366485240852280">"확인"</string> </resources> diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 12a50123f..46d6c6b43 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Мультимедия"</string> <string name="storage_description" msgid="4081716890357580107">"Жергиликтүү сактагыч"</string> <string name="app_label" msgid="9035307001052716210">"Медиа сактагыч"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Медиа"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Медиа файлдарды тандагыч"</string> <string name="artist_label" msgid="8105600993099120273">"Аткаруучу"</string> <string name="unknown" msgid="2059049215682829375">"Белгисиз"</string> <string name="root_images" msgid="5861633549189045666">"Сүрөттөр"</string> @@ -46,12 +46,15 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Төмөнкүдөн алынган булуттагы мультимедианы колдонуу:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Жок"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Мультимедиа колдонмосу өзгөргөн жок."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Медиа файлдарды тандагыч"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Медиа файлдарды тандагыч"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Медиа файлдар шайкештирилүүдө…"</string> <string name="add" msgid="2894574044585549298">"Кошуу"</string> <string name="deselect" msgid="4297825044827769490">"Тандоодон чыгаруу"</string> <string name="deselected" msgid="8488133193326208475">"Тандоодон чыгарылды"</string> <string name="select" msgid="2704765470563027689">"Тандоо"</string> <string name="selected" msgid="9151797369975828124">"Тандалды"</string> - <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> объектке чейин тандаңыз}other{<xliff:g id="COUNT_1">^1</xliff:g> объектке чейин тандаңыз}}"</string> + <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> нерсеге чейин тандаңыз}other{<xliff:g id="COUNT_1">^1</xliff:g> нерсеге чейин тандаңыз}}"</string> <string name="recent" msgid="6694613584743207874">"Акыркы"</string> <string name="picker_photos_empty_message" msgid="5980619500554575558">"Сүрөттөр же видеолор жок"</string> <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Колдоого алынган сүрөттөр же видеолор жок"</string> @@ -67,7 +70,7 @@ <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Жеке маалыматка жумуш колдонмосунан кирүүгө тыюу салынат"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"Жумуш колдонмолору тындырылды"</string> <string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"Жумуш сүрөттөрүн ачуу үчүн жумуш колдонмолорун иштетип, кайра аракет кылыңыз"</string> - <string name="picker_privacy_message" msgid="9132700451027116817">"Бул колдонмо сиз тандаган сүрөттөргө гана кире алат"</string> + <string name="picker_privacy_message" msgid="9132700451027116817">"Бул колдонмого сиз тандаган сүрөттөр гана жеткиликтүү"</string> <string name="picker_header_permissions" msgid="675872774407768495">"Бул колдонмо кире турган сүрөттөрдү жана видеолорду тандаңыз"</string> <string name="picker_album_item_count" msgid="4420723302534177596">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> нерсе}other{<xliff:g id="COUNT_1">^1</xliff:g> нерсе}}"</string> <string name="picker_add_button_multi_select" msgid="4005164092275518399">"Кошуу (<xliff:g id="COUNT">^1</xliff:g>)"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Интернет байланышыңызды текшерип, кайталап көрүңүз"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Кайталоо"</string> <string name="not_selected" msgid="2244008151669896758">"тандалган жок"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Тандаган медиа файлдарыңыз даярдалууда"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> даяр"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Эми камдык көчүрмөсү сакталган сүрөттөр камтылат"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> аккаунтундагы (<xliff:g id="USER_ACCOUNT">%2$s</xliff:g>) сүрөттөрдү тандай аласыз"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Колдонмо тандаңыз"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Аккаунт тандоо"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Аккаунтту өзгөртүү"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Бардык сүрөттөрүңүз алынууда"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> колдонмосу бул аудио файлды өзгөртсүнбү?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> колдонмосу <xliff:g id="COUNT">^2</xliff:g> аудио файлды өзгөртсүнбү?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Аудио файл өзгөртүлүүдө…}other{<xliff:g id="COUNT">^1</xliff:g> аудио файл өзгөртүлүүдө…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> колдонмосу бул видеону өзгөртсүнбү?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> колдонмосу <xliff:g id="COUNT">^2</xliff:g> видеону өзгөртсүнбү?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Коопсуздукту коргоо"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Камтылган транскоддоо эскертүүлөрү"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Камтылган транскоддоо жүргүзүлүүдө"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Айрым сүрөттөр жүктөлбөй жатат"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Түшүндүм"</string> </resources> diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index dcbb981e8..a9a2ac288 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"ມີເດຍ"</string> <string name="storage_description" msgid="4081716890357580107">"ບ່ອນຈັດເກັບຂໍ້ມູນໃນເຄື່ອງ"</string> <string name="app_label" msgid="9035307001052716210">"ພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີເດຍ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"ສື່"</string> + <string name="picker_app_label" msgid="1195424381053599122">"ຕົວເລືອກມີເດຍ"</string> <string name="artist_label" msgid="8105600993099120273">"ສິນລະປິນ"</string> <string name="unknown" msgid="2059049215682829375">"ບໍ່ຮູ້ຈັກ"</string> <string name="root_images" msgid="5861633549189045666">"ຮູບພາບ"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ເຂົ້າເຖິງມີເດຍໃນລະບົບຄລາວຈາກ"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ບໍ່ມີ"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"ບໍ່ສາມາດປ່ຽນແອັບມີເດຍໃນລະບົບຄລາວໄດ້ໃນຕອນນີ້."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"ຕົວເລືອກມີເດຍ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"ຕົວເລືອກມີເດຍ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"ກຳລັງຊິ້ງຂໍ້ມູນມີເດຍ…"</string> <string name="add" msgid="2894574044585549298">"ເພີ່ມ"</string> <string name="deselect" msgid="4297825044827769490">"ເຊົາເລືອກ"</string> <string name="deselected" msgid="8488133193326208475">"ເຊົາເລືອກແລ້ວ"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ກະລຸນາກວດສອບການເຊື່ອມຕໍ່ອິນເຕີເນັດຂອງທ່ານແລ້ວລອງໃໝ່"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ລອງໃໝ່"</string> <string name="not_selected" msgid="2244008151669896758">"ບໍ່ໄດ້ເລືອກ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"ກຳລັງກຽມມີເດຍທີ່ທ່ານເລືອກໄວ້"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"ພ້ອມແລ້ວ <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ຕອນນີ້ຮວມຮູບພາບທີ່ສຳຮອງຂໍ້ມູນໄວ້ແລ້ວ"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"ທ່ານສາມາດເລືອກຮູບພາບໄດ້ຈາກບັນຊີ <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ເລືອກແອັບ"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"ເລືອກບັນຊີ"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ປ່ຽນບັນຊີ"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"ກຳລັງໂຫຼດຮູບພາບທັງໝົດຂອງທ່ານ"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{ອະນຸຍາດໃຫ້ <xliff:g id="APP_NAME_0">^1</xliff:g> ແກ້ໄຂໄຟລ໌ສຽງນີ້ບໍ?}other{ອະນຸຍາດໃຫ້ <xliff:g id="APP_NAME_1">^1</xliff:g> ແກ້ໄຂໄຟລ໌ສຽງ <xliff:g id="COUNT">^2</xliff:g> ໄຟລ໌ບໍ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ກຳລັງແກ້ໄຂໄຟລ໌ສຽງ…}other{ກຳລັງແກ້ໄຂໄຟລ໌ສຽງ <xliff:g id="COUNT">^1</xliff:g> ໄຟລ໌…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{ອະນຸຍາດໃຫ້ <xliff:g id="APP_NAME_0">^1</xliff:g> ແກ້ໄຂວິດີໂອນີ້ບໍ?}other{ອະນຸຍາດໃຫ້ <xliff:g id="APP_NAME_1">^1</xliff:g> ແກ້ໄຂວິດີໂອ <xliff:g id="COUNT">^2</xliff:g> ລາຍການບໍ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"ການປ້ອງກັນຄວາມປອດໄພ"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"ແຈ້ງເຕືອນການປ່ຽນຮູບແບບລະຫັດເດີມ"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"ຄວາມຄືບໜ້າຂອງການປ່ຽນຮູບແບບລະຫັດເດີມ"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"ບໍ່ສາມາດໂຫຼດບາງຮູບພາບໄດ້"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ເຂົ້າໃຈແລ້ວ"</string> </resources> diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index 0767478c1..5d6c4287a 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Medija"</string> <string name="storage_description" msgid="4081716890357580107">"Vietinė saugykla"</string> <string name="app_label" msgid="9035307001052716210">"Medijos saugykla"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Medija"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Medijos pasirinkimo priemonė"</string> <string name="artist_label" msgid="8105600993099120273">"Atlikėjas"</string> <string name="unknown" msgid="2059049215682829375">"Nežinoma"</string> <string name="root_images" msgid="5861633549189045666">"Vaizdai"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Pasiekti mediją debesyje iš"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Nėra"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Šiuo metu nepavyko pakeisti debesies medijos programos."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Medijos pasirinkimo priemonė"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Medijos pasirinkimo priemonė"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sinchronizuojama medija…"</string> <string name="add" msgid="2894574044585549298">"Pridėti"</string> <string name="deselect" msgid="4297825044827769490">"Panaikinti pasirinkimą"</string> <string name="deselected" msgid="8488133193326208475">"Pasirinkimas panaikintas"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Patikrinkite interneto ryšį ir bandykite dar kartą"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Bandyti dar kartą"</string> <string name="not_selected" msgid="2244008151669896758">"nepasirinkta"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Ruošiami pasirinkti medijos failai"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Paruošta: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> iš <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Dabar įtraukiamos atsarginės nuotraukų kopijos"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Galite pasirinkti nuotraukas iš „<xliff:g id="APP_NAME">%1$s</xliff:g>“ paskyros <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Pasirinkti programą"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Pasirinkti paskyrą"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Pakeisti paskyrą"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Gaunamos visos nuotraukos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Leisti programai „<xliff:g id="APP_NAME_0">^1</xliff:g>“ keisti šį garso failą?}one{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> garso failą?}few{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> garso failus?}many{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> garso failo?}other{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> garso failų?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Keičiamas garso failas…}one{Keičiamas <xliff:g id="COUNT">^1</xliff:g> garso failas…}few{Keičiami <xliff:g id="COUNT">^1</xliff:g> garso failai…}many{Keičiama <xliff:g id="COUNT">^1</xliff:g> garso failo…}other{Keičiama <xliff:g id="COUNT">^1</xliff:g> garso failų…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Leisti programai „<xliff:g id="APP_NAME_0">^1</xliff:g>“ keisti šį vaizdo įrašą?}one{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> vaizdo įrašą?}few{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> vaizdo įrašus?}many{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> vaizdo įrašo?}other{Leisti programai „<xliff:g id="APP_NAME_1">^1</xliff:g>“ keisti <xliff:g id="COUNT">^2</xliff:g> vaizdo įrašų?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Apsauga"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native Transcode Alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native Transcode Progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Nepavyko įkelti kai kurių nuotraukų"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Supratau"</string> </resources> diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index e8df90906..178f65582 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multivide"</string> <string name="storage_description" msgid="4081716890357580107">"Lokālā krātuve"</string> <string name="app_label" msgid="9035307001052716210">"Multivides krātuve"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Multivide"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Multivides atlasītājs"</string> <string name="artist_label" msgid="8105600993099120273">"Izpildītājs"</string> <string name="unknown" msgid="2059049215682829375">"Nezināms"</string> <string name="root_images" msgid="5861633549189045666">"Attēli"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Piekļūstiet mākoņa multivides saturam no"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Nav"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Nevarēja mainīt mākoņa multivides lietotni."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Multivides atlasītājs"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Multivides atlasītājs"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Notiek multivides satura sinhronizēšana…"</string> <string name="add" msgid="2894574044585549298">"Pievienot"</string> <string name="deselect" msgid="4297825044827769490">"Noņemt atlasi"</string> <string name="deselected" msgid="8488133193326208475">"Atlase noņemta"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Pārbaudiet interneta savienojumu un mēģiniet vēlreiz"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Mēģināt vēlreiz"</string> <string name="not_selected" msgid="2244008151669896758">"nav atlasīts"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Notiek jūsu atlasītā multivides satura sagatavošana"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Gatavs: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> no <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Dublētie fotoattēli ir iekļauti"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Varat atlasīt fotoattēlus no lietotnes “<xliff:g id="APP_NAME">%1$s</xliff:g>” konta <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Izvēlēties lietotni"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Izvēlēties kontu"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Mainīt kontu"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Notiek visu jūsu fotoattēlu ielāde…"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Vai atļaut lietotnei <xliff:g id="APP_NAME_0">^1</xliff:g> pārveidot šo audio failu?}zero{Vai atļaut lietotnei <xliff:g id="APP_NAME_1">^1</xliff:g> pārveidot <xliff:g id="COUNT">^2</xliff:g> audio failus?}one{Vai atļaut lietotnei <xliff:g id="APP_NAME_1">^1</xliff:g> pārveidot <xliff:g id="COUNT">^2</xliff:g> audio failu?}other{Vai atļaut lietotnei <xliff:g id="APP_NAME_1">^1</xliff:g> pārveidot <xliff:g id="COUNT">^2</xliff:g> audio failus?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Notiek audio faila pārveidošana…}zero{Notiek <xliff:g id="COUNT">^1</xliff:g> audio failu pārveidošana…}one{Notiek <xliff:g id="COUNT">^1</xliff:g> audio faila pārveidošana…}other{Notiek <xliff:g id="COUNT">^1</xliff:g> audio failu pārveidošana…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Vai atļaut lietotnei <xliff:g id="APP_NAME_0">^1</xliff:g> pārveidot šo videoklipu?}zero{Vai atļaut lietotnei <xliff:g id="APP_NAME_1">^1</xliff:g> pārveidot <xliff:g id="COUNT">^2</xliff:g> videoklipus?}one{Vai atļaut lietotnei <xliff:g id="APP_NAME_1">^1</xliff:g> pārveidot <xliff:g id="COUNT">^2</xliff:g> videoklipu?}other{Vai atļaut lietotnei <xliff:g id="APP_NAME_1">^1</xliff:g> pārveidot <xliff:g id="COUNT">^2</xliff:g> videoklipus?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Drošības aizsardzība"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Brīdinājumi par mantotā formāta pārkodēšanu"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Mantotā formāta pārkodēšanas norise"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Nevar ielādēt dažus fotoattēlus"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Labi"</string> </resources> diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index f7d31b2b5..c908243aa 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Аудио-визуелни содржини"</string> <string name="storage_description" msgid="4081716890357580107">"Локална меморија"</string> <string name="app_label" msgid="9035307001052716210">"Капацитет за аудиовизуелни содржини"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Аудиовизуелни содржини"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Избирач на аудиовизуелни содржини"</string> <string name="artist_label" msgid="8105600993099120273">"Изведувач"</string> <string name="unknown" msgid="2059049215682829375">"Непознат"</string> <string name="root_images" msgid="5861633549189045666">"Слики"</string> @@ -42,10 +42,13 @@ <string name="picker_settings" msgid="6443463167344790260">"Апликација за содржини во облак"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Апликација за содржини во облак"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Апликација за аудиовизуелни содржини во облак"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Пристап до вашите аудиовизуелни содржини во облак кога некоја апликација или веб-сајт ќе ве праша да изберете фотографии или видеа"</string> - <string name="picker_settings_selection_message" msgid="245453573086488596">"Пристапете до аудиовизуелните содржини во облак од"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Пристапувајте до вашите аудиовизуелни содржини во облак кога некоја апликација или веб-сајт ќе побара да изберете фотографии или видеа"</string> + <string name="picker_settings_selection_message" msgid="245453573086488596">"Пристапувајте до аудиовизуелните содржини во облак од"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Нема"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Не може да се промени апликацијата за аудиовизуелни содржини во облак во моментов."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Избирач на аудиовизуелни содржини"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Избирач на аудиовизуелни содржини"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Се синхронизираат аудиовизуелните содржини…"</string> <string name="add" msgid="2894574044585549298">"Додај"</string> <string name="deselect" msgid="4297825044827769490">"Поништи го изборот"</string> <string name="deselected" msgid="8488133193326208475">"Изборот е поништен"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Фотографии"</string> <string name="picker_albums" msgid="4822511902115299142">"Албуми"</string> <string name="picker_preview" msgid="6257414886055861039">"Преглед"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Префрли на работен профил"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Префрли на личен профил"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Префрлете се на работен профил"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Префрлете се на личен профил"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Блокирано од администраторот"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Не е дозволено пристапување до работни податоци од лична апликација"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Не е дозволено пристапување до лични податоци од работна апликација"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Проверете ја интернет-врската и обидете се повторно"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Повторно"</string> <string name="not_selected" msgid="2244008151669896758">"не е избрано"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Вашите избрани аудиовизуелни содржини се подготвуваат"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Подготвени: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> од <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Бекап од фотографиите сега е влучен"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Сега се опфатени фотографии од бекап"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Можете да изберете фотографии од сметката <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> на <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"Сметката на <xliff:g id="APP_NAME">%1$s</xliff:g> е ажурирана"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Фотографиите од <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> сега се вклучени овде"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Изберете апликација"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Изберете сметка"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Променете ја сметката"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Се вчитуваат сите ваши фотографии"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Да се дозволи <xliff:g id="APP_NAME_0">^1</xliff:g> да ја измени аудиодатотекава?}one{Да се дозволи <xliff:g id="APP_NAME_1">^1</xliff:g> да измени <xliff:g id="COUNT">^2</xliff:g> аудиодатотека?}other{Да се дозволи <xliff:g id="APP_NAME_1">^1</xliff:g> да измени <xliff:g id="COUNT">^2</xliff:g> аудиодатотеки?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Се изменува аудиодатотеката…}one{Се изменуваат <xliff:g id="COUNT">^1</xliff:g> аудиодатотека…}other{Се изменуваат <xliff:g id="COUNT">^1</xliff:g> аудиодатотеки…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Да се дозволи <xliff:g id="APP_NAME_0">^1</xliff:g> да го измени видеово?}one{Да се дозволи <xliff:g id="APP_NAME_1">^1</xliff:g> да измени <xliff:g id="COUNT">^2</xliff:g> видео?}other{Да се дозволи <xliff:g id="APP_NAME_1">^1</xliff:g> да измени <xliff:g id="COUNT">^2</xliff:g> видеа?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Безбедносна заштита"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Предупредувања за матичното транскодирање"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Напредок на матичното транскодирање"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Некои фотографии не може да се вчитаат"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Сфатив"</string> </resources> diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index ac564d182..c2728515c 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"മീഡിയ"</string> <string name="storage_description" msgid="4081716890357580107">"ലോക്കൽ സ്റ്റോറേജ്"</string> <string name="app_label" msgid="9035307001052716210">"മീഡിയ സ്റ്റോറേജ്"</string> - <string name="picker_app_label" msgid="4254039089502164761">"മീഡിയ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"മീഡിയ പിക്കർ"</string> <string name="artist_label" msgid="8105600993099120273">"ആർട്ടിസ്റ്റ്"</string> <string name="unknown" msgid="2059049215682829375">"അജ്ഞാതം"</string> <string name="root_images" msgid="5861633549189045666">"ചിത്രങ്ങൾ"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ക്ലൗഡ് മീഡിയ ആപ്പിൽ നിന്ന്"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ഒന്നുമില്ല"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"ക്ലൗഡ് മീഡിയ ആപ്പ് ഇപ്പോൾ മാറ്റാനാകുന്നില്ല."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"മീഡിയാ പിക്കർ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"മീഡിയാ പിക്കർ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"മീഡിയാ സമന്വയിപ്പിക്കുന്നു…"</string> <string name="add" msgid="2894574044585549298">"ചേർക്കുക"</string> <string name="deselect" msgid="4297825044827769490">"തിരഞ്ഞെടുത്തത് മാറ്റുക"</string> <string name="deselected" msgid="8488133193326208475">"തിരഞ്ഞെടുത്തത് മാറ്റി"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"നിങ്ങളുടെ ഇന്റർനെറ്റ് കണക്ഷൻ പരിശോധിച്ച് വീണ്ടും ശ്രമിക്കുക"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"വീണ്ടും ശ്രമിക്കുക"</string> <string name="not_selected" msgid="2244008151669896758">"തിരഞ്ഞെടുത്തിട്ടില്ല"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"നിങ്ങൾ തിരഞ്ഞെടുത്ത മീഡിയ തയ്യാറാക്കുന്നു"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>-ൽ <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> എണ്ണം തയ്യാറാണ്"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ബാക്കപ്പ് ചെയ്ത ഫോട്ടോകൾ ഇപ്പോൾ ഉൾപ്പെടുത്തിയിരിക്കുന്നു"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"നിങ്ങൾക്ക് <xliff:g id="APP_NAME">%1$s</xliff:g> അക്കൗണ്ടിൽ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> നിന്ന് ഫോട്ടോകൾ തിരഞ്ഞെടുക്കാം"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ആപ്പ് തിരഞ്ഞെടുക്കുക"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"അക്കൗണ്ട് തിരഞ്ഞെടുക്കുക"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"അക്കൗണ്ട് മാറ്റുക"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"നിങ്ങളുടെ ഫോട്ടോകളെല്ലാം ലഭ്യമാക്കുന്നു"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{ഈ ഓഡിയോ ഫയൽ പരിഷ്ക്കരിക്കാൻ <xliff:g id="APP_NAME_0">^1</xliff:g> എന്നതിനെ അനുവദിക്കണോ?}other{<xliff:g id="COUNT">^2</xliff:g> ഓഡിയോ ഫയലുകൾ പരിഷ്ക്കരിക്കാൻ <xliff:g id="APP_NAME_1">^1</xliff:g> എന്നതിനെ അനുവദിക്കണോ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ഓഡിയോ ഫയൽ പരിഷ്ക്കരിക്കുന്നു…}other{<xliff:g id="COUNT">^1</xliff:g> ഓഡിയോ ഫയലുകൾ പരിഷ്ക്കരിക്കുന്നു…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{ഈ വീഡിയോ പരിഷ്ക്കരിക്കാൻ <xliff:g id="APP_NAME_0">^1</xliff:g> എന്നതിനെ അനുവദിക്കണോ?}other{<xliff:g id="COUNT">^2</xliff:g> വീഡിയോകൾ പരിഷ്ക്കരിക്കാൻ <xliff:g id="APP_NAME_1">^1</xliff:g> എന്നതിനെ അനുവദിക്കണോ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"സുരക്ഷാ പരിരക്ഷ"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"നേറ്റീവ് ട്രാൻസ്കോഡ് മുന്നറിയിപ്പുകൾ"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"നേറ്റീവ് ട്രാൻസ്കോഡ് പുരോഗതി"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"ചില ഫോട്ടോകൾ ലോഡ് ചെയ്യാനാകുന്നില്ല"</string> + <string name="dialog_button_text" msgid="351366485240852280">"മനസ്സിലായി"</string> </resources> diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index f688f7dd1..2ef0cf6b4 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -19,11 +19,11 @@ <string name="uid_label" msgid="8421971615411294156">"Медиа"</string> <string name="storage_description" msgid="4081716890357580107">"Дотоод сан"</string> <string name="app_label" msgid="9035307001052716210">"Медиа санах ой"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Медиа"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Медиа сонгогч"</string> <string name="artist_label" msgid="8105600993099120273">"Уран бүтээлч"</string> <string name="unknown" msgid="2059049215682829375">"Тодорхойгүй"</string> <string name="root_images" msgid="5861633549189045666">"Зураг"</string> - <string name="root_videos" msgid="8792703517064649453">"Бичлэг"</string> + <string name="root_videos" msgid="8792703517064649453">"Видео"</string> <string name="root_audio" msgid="3505830755201326018">"Аудио"</string> <string name="root_documents" msgid="3829103301363849237">"Документ"</string> <string name="permission_required" msgid="1460820436132943754">"Энэ зүйлийг өөрчлөх эсвэл устгахад зөвшөөрөл шаардлагатай."</string> @@ -42,10 +42,13 @@ <string name="picker_settings" msgid="6443463167344790260">"Үүлэн медиа апп"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Үүлэн медиа апп"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Үүлэн медиа апп"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Апп эсвэл вебсайт танаас зураг эсвэл видео сонгохыг хүсэх үед таны үүлэн медиадаа хандана уу"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Апп эсвэл вебсайт танаас зураг эсвэл видео сонгохыг хүсвэл үүлэн медиадаа хандана уу"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Дараахаас үүлэн медиад хандах"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Байхгүй"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Энэ удаад үүлэн медиа аппыг өөрчилж чадсангүй."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Медиа сонгогч"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Медиа сонгогч"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Медиаг синк хийж байна…"</string> <string name="add" msgid="2894574044585549298">"Нэмэх"</string> <string name="deselect" msgid="4297825044827769490">"Сонголтыг цуцлах"</string> <string name="deselected" msgid="8488133193326208475">"Сонголтыг цуцалсан"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Интернэт холболтоо шалгаад, дахин оролдоно уу"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Дахин оролдох"</string> <string name="not_selected" msgid="2244008151669896758">"сонгоогүй"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Таны сонгосон медиаг бэлтгэж байна"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>-с <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> бэлэн"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Одоо хуулбарласан зургийг багтаасан"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Та <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> бүртгэлээс зураг сонгох боломжтой"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Апп сонгох"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Бүртгэл сонгох"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Бүртгэл өөрчлөх"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Таны бүх зургийг авч байна"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>-д энэ аудио файлыг өөрчлөхийг зөвшөөрөх үү?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>-д <xliff:g id="COUNT">^2</xliff:g> аудио файлыг өөрчлөхийг зөвшөөрөх үү?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Аудио файлыг өөрчилж байна…}other{<xliff:g id="COUNT">^1</xliff:g> аудио файлыг өөрчилж байна…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g>-д энэ видеог өөрчлөхийг зөвшөөрөх үү?}other{<xliff:g id="APP_NAME_1">^1</xliff:g>-д <xliff:g id="COUNT">^2</xliff:g> видеог өөрчлөхийг зөвшөөрөх үү?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Аюулгүй байдлын хамгаалалт"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Уугуул хөрвүүлгийн сэрэмжлүүлэг"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Уугуул хөрвүүлгийн явц"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Зарим зургийг ачаалах боломжгүй"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Ойлголоо"</string> </resources> diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 563aac436..4805f63a3 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"मीडिया"</string> <string name="storage_description" msgid="4081716890357580107">"स्थानिक स्टोरेज"</string> <string name="app_label" msgid="9035307001052716210">"मीडिया स्टोरेज"</string> - <string name="picker_app_label" msgid="4254039089502164761">"मीडिया"</string> + <string name="picker_app_label" msgid="1195424381053599122">"मीडिया पिकर"</string> <string name="artist_label" msgid="8105600993099120273">"कलाकार"</string> <string name="unknown" msgid="2059049215682829375">"अज्ञात"</string> <string name="root_images" msgid="5861633549189045666">"इमेज"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"येथून क्लाउड मीडिया अॅक्सेस करा"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"काहीही नाही"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"क्लाउड मीडिया अॅप या क्षणी बदलू शकत नाही."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"मीडिया पिकर"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"मीडिया पिकर"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"मीडिया सिंक करत आहे…"</string> <string name="add" msgid="2894574044585549298">"जोडा"</string> <string name="deselect" msgid="4297825044827769490">"निवड रद्द करा"</string> <string name="deselected" msgid="8488133193326208475">"निवड रद्द केली आहे"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"तुमचे इंटरनेट कनेक्शन तपासा आणि पुन्हा प्रयत्न करा"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"पुन्हा प्रयत्न करा"</string> <string name="not_selected" msgid="2244008151669896758">"निवडला नाही"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"तुमचा निवडलेला मीडिया तयार करत आहे"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> तयार"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"बॅकअप घेतलेल्या फोटोचा आता समावेश केला आहे"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"तुम्ही <xliff:g id="APP_NAME">%1$s</xliff:g> खात्याच्या <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> वरून फोटो निवडू शकता"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ॲप निवडा"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"खाते निवडा"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"खाते बदला"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"तुमचे सर्व फोटो मिळवत आहे"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ला या ऑडिओ फाइलमध्ये फेरबदल करण्याची अनुमती द्यायची आहे का?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> ला <xliff:g id="COUNT">^2</xliff:g> ऑडिओ फाइलमध्ये फेरबदल करण्याची अनुमती द्यायची आहे का?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ऑडिओ फाइलमध्ये फेरबदल करत आहे…}other{<xliff:g id="COUNT">^1</xliff:g> ऑडिओ फाइलमध्ये फेरबदल करत आहे…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ला या व्हिडिओमध्ये फेरबदल करण्याची अनुमती द्यायची आहे का?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> ला <xliff:g id="COUNT">^2</xliff:g> व्हिडिओमध्ये फेरबदल करण्याची अनुमती द्यायची आहे का?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"सुरक्षितता संरक्षण"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"मूळ ट्रान्सकोड सूचना"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"मूळ ट्रान्सकोड प्रगती"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"काही फोटो लोड करू शकत नाही"</string> + <string name="dialog_button_text" msgid="351366485240852280">"समजले"</string> </resources> diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 1c09a563d..5085b7c5c 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Storan setempat"</string> <string name="app_label" msgid="9035307001052716210">"Storan Media"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Pemilih Media"</string> <string name="artist_label" msgid="8105600993099120273">"Artis"</string> <string name="unknown" msgid="2059049215682829375">"Tidak diketahui"</string> <string name="root_images" msgid="5861633549189045666">"Imej"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Akses media awan daripada"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Tiada"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Tidak dapat menukar apl media awan pada masa ini."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Pemilih media"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Pemilih media"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Menyegerakkan media…"</string> <string name="add" msgid="2894574044585549298">"Tambah"</string> <string name="deselect" msgid="4297825044827769490">"Nyahpilih"</string> <string name="deselected" msgid="8488133193326208475">"Dinyahpilih"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Semak sambungan Internet anda, kemudian cuba lagi"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Cuba lagi"</string> <string name="not_selected" msgid="2244008151669896758">"tidak dipilih"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Menyediakan media pilihan anda"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> daripada <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> sudah bersedia"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Foto yang disandarkan kini disertakan"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Anda boleh memilih foto daripada akaun <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Pilih apl"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Pilih akaun"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Tukar akaun"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Mendapatkan semua foto anda"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Benarkan <xliff:g id="APP_NAME_0">^1</xliff:g> mengubah suai fail audio ini?}other{Benarkan <xliff:g id="APP_NAME_1">^1</xliff:g> mengubah suai <xliff:g id="COUNT">^2</xliff:g> fail audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Mengubah suai fail audio…}other{Mengubah suai <xliff:g id="COUNT">^1</xliff:g> fail audio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Benarkan <xliff:g id="APP_NAME_0">^1</xliff:g> mengubah suai video ini?}other{Benarkan <xliff:g id="APP_NAME_1">^1</xliff:g> mengubah suai <xliff:g id="COUNT">^2</xliff:g> video?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Perlindungan keselamatan"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Amaran Transkod Asal"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Kemajuan Transkod Asal"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Tidak dapat memuatkan beberapa Foto"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 867a49de8..2df7bda22 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"မီဒီယာ"</string> <string name="storage_description" msgid="4081716890357580107">"စက်တွင်း သိုလှောင်ခန်း"</string> <string name="app_label" msgid="9035307001052716210">"မီဒီယာ သိုလှောင်ခန်း"</string> - <string name="picker_app_label" msgid="4254039089502164761">"မီဒီယာ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"မီဒီယာရွေးရန်"</string> <string name="artist_label" msgid="8105600993099120273">"အနုပညာရှင်"</string> <string name="unknown" msgid="2059049215682829375">"အမျိုးအမည်မသိ"</string> <string name="root_images" msgid="5861633549189045666">"ပုံများ"</string> @@ -42,10 +42,13 @@ <string name="picker_settings" msgid="6443463167344790260">"Cloud မီဒီယာအက်ပ်"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Cloud မီဒီယာအက်ပ်"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Cloud မီဒီယာအက်ပ်"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"အက်ပ် (သို့) ဝဘ်ဆိုက်က သင့်အား ဓာတ်ပုံ (သို့) ဗီဒီယိုများ ရွေးခိုင်းသောအခါ သင်၏ cloud မီဒီယာကို ဝင်ပါ"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"အက်ပ် (သို့) ဝဘ်ဆိုက်က သင့်အား ဓာတ်ပုံ (သို့) ဗီဒီယိုများ ရွေးခိုင်းသောအခါ သင်၏ cloud မီဒီယာကို ဝင်သည်"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Cloud မီဒီယာကို ဤနေရာမှ ဝင်သုံးရန်"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"မရှိ"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"လောလောဆယ် cloud မီဒီယာ အက်ပ်ကို ပြောင်း၍မရပါ။"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"မီဒီယာရွေးခြင်း"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"မီဒီယာရွေးခြင်း"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"မီဒီယာကို စင့်ခ်လုပ်နေသည်…"</string> <string name="add" msgid="2894574044585549298">"ထည့်ရန်"</string> <string name="deselect" msgid="4297825044827769490">"မရွေးပါနှင့်"</string> <string name="deselected" msgid="8488133193326208475">"ရွေးချယ်မထားပါ"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"သင်၏ အင်တာနက် ချိတ်ဆက်မှုကို စစ်ဆေးပြီး ထပ်စမ်းကြည့်ပါ"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ထပ်စမ်းကြည့်ရန်"</string> <string name="not_selected" msgid="2244008151669896758">"ရွေးချယ်မထားပါ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"သင်ရွေးထားသော မီဒီယာကို ပြင်ဆင်နေသည်"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> အနက် <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> အသင့်ဖြစ်ပြီ"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"အရန်သိမ်းထားသော ဓာတ်ပုံများ ယခုထည့်သွင်းထားပြီ"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> အကောင့်မှ ဓာတ်ပုံများ ရွေးနိုင်သည်"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> အကောင့် <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> မှ ဓာတ်ပုံများ ရွေးနိုင်သည်"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g> အကောင့် အပ်ဒိတ်လုပ်လိုက်သည်"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"<xliff:g id="USER_ACCOUNT">%1$s</xliff:g> မှ ဓာတ်ပုံများကို ဤနေရာတွင် ယခုထည့်သွင်းထားပါပြီ"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"cloud မီဒီယာအက်ပ် ရွေးရန်"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"အက်ပ်ရွေးရန်"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"အကောင့်ရွေးရန်"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"အကောင့်ပြောင်းရန်"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"သင့်ဓာတ်ပုံအားလုံးကို ရယူနေသည်"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ကို ဤအသံဖိုင် ပြင်ဆင်ခွင့်ပြုမလား။}other{<xliff:g id="APP_NAME_1">^1</xliff:g> ကို အသံဖိုင် <xliff:g id="COUNT">^2</xliff:g> ဖိုင် ပြင်ဆင်ခွင့်ပြုမလား။}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{အသံဖိုင်ကို ပြင်ဆင်နေသည်…}other{အသံဖိုင် <xliff:g id="COUNT">^1</xliff:g> ခုကို ပြင်ဆင်နေသည်…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ကို ဤဗီဒီယို ပြင်ဆင်ခွင့်ပြုမလား။}other{<xliff:g id="APP_NAME_1">^1</xliff:g> ကို ဗီဒီယို <xliff:g id="COUNT">^2</xliff:g> ခု ပြင်ဆင်ခွင့်ပြုမလား။}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"လုံခြုံရေး ကာကွယ်မှု"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"မူရင်းမီဒီယာကုဒ်ပြောင်းသည့် သတိပေးချက်များ"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"မူရင်းမီဒီယာကုဒ်ပြောင်းသည့် အခြေအနေ"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"ဓာတ်ပုံအချို့ကို ဖွင့်၍ မရပါ"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ရပြီ"</string> </resources> diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 6507c11c2..7ab3ea88a 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Medier"</string> <string name="storage_description" msgid="4081716890357580107">"Lokal lagring"</string> <string name="app_label" msgid="9035307001052716210">"Medielagring"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Medier"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Medievelger"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Ukjent"</string> <string name="root_images" msgid="5861633549189045666">"Bilder"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Åpne skymedier fra"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ingen"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Kunne ikke endre skymedieappen akkurat nå."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Medievelger"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Medievelger"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synkroniserer medieinnholdet …"</string> <string name="add" msgid="2894574044585549298">"Legg til"</string> <string name="deselect" msgid="4297825044827769490">"Fjern merking"</string> <string name="deselected" msgid="8488133193326208475">"Ikke valgt"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Sjekk internettilkoblingen og prøv på nytt"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Prøv på nytt"</string> <string name="not_selected" msgid="2244008151669896758">"ikke valgt"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Klargjør det valgte medieinnholdet"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> av <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> er klare"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Nå er sikkerhetskopierte bilder inkludert"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Du kan velge bilder fra <xliff:g id="APP_NAME">%1$s</xliff:g>-kontoen <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Velg app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Velg konto"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Bytt konto"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Laster inn alle bildene dine"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Vil du tillate at <xliff:g id="APP_NAME_0">^1</xliff:g> endrer denne lydfilen?}other{Vil du tillate at <xliff:g id="APP_NAME_1">^1</xliff:g> endrer <xliff:g id="COUNT">^2</xliff:g> lydfiler?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Endrer lydfilen …}other{Endrer <xliff:g id="COUNT">^1</xliff:g> lydfiler …}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Vil du tillate at <xliff:g id="APP_NAME_0">^1</xliff:g> endrer denne videoen?}other{Vil du tillate at <xliff:g id="APP_NAME_1">^1</xliff:g> endrer <xliff:g id="COUNT">^2</xliff:g> videoer?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Beskyttelse"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Integrerte omkodingsvarsler"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Integrert omkodingsfremdrift"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Noen bilder kan ikke lastes inn"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Greit"</string> </resources> diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 09749c198..600979d57 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"मिडिया"</string> <string name="storage_description" msgid="4081716890357580107">"स्थानीय भण्डारण"</string> <string name="app_label" msgid="9035307001052716210">"मिडिया भण्डारण"</string> - <string name="picker_app_label" msgid="4254039089502164761">"मिडिया"</string> + <string name="picker_app_label" msgid="1195424381053599122">"मिडिया पिकर"</string> <string name="artist_label" msgid="8105600993099120273">"कलाकार"</string> <string name="unknown" msgid="2059049215682829375">"अज्ञात"</string> <string name="root_images" msgid="5861633549189045666">"फोटो"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"यसबाट क्लाउड मिडिया प्रयोग गर्नुहोस्"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"कुनै पनि होइन"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"अहिले क्लाउड मिडिया एप परिवर्तन गर्न सकिएन।"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"मिडिया पिकर"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"मिडिया पिकर"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"मिडिया सिंक हुँदै छ…"</string> <string name="add" msgid="2894574044585549298">"हाल्नुहोस्"</string> <string name="deselect" msgid="4297825044827769490">"चयन रद्द गर्नुहोस्"</string> <string name="deselected" msgid="8488133193326208475">"चयन रद्द गरियो"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"इन्टरनेट जाँच्नुहोस् र फेरि प्रयास गर्नुहोस्"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"फेरि प्रयास गर्नुहोस्"</string> <string name="not_selected" msgid="2244008151669896758">"चयन गरिएको छैन"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"तपाईंले चयन गर्नुभएको मिडिया तयार गरिँदै छ"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> मध्ये <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> वटा फोटो तयार छन्"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"अब ब्याकअप गरिएका फोटोहरू समावेश गरिएका छन्"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"तपाईं <xliff:g id="APP_NAME">%1$s</xliff:g> मा <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> खाता प्रयोग गरी राखिएका फोटोहरू चयन गर्न सक्नुहुन्छ"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"एप छनौट गर्नुहोस्"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"खाता छनौट गर्नुहोस्"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"खाता बदल्नुहोस्"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"तपाईंका सबै फोटोहरू प्राप्त गरिँदै छन्"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> लाई यो अडियो फाइल परिमार्जन गर्न दिने हो?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> लाई <xliff:g id="COUNT">^2</xliff:g> वटा अडियो फाइल परिमार्जन गर्न दिने हो?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{अडियो फाइल परिमार्जन गरिँदै छ…}other{<xliff:g id="COUNT">^1</xliff:g> वटा अडियो फाइल परिमार्जन गरिँदै छन्…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> लाई यो भिडियो परिमार्जन गर्न दिने हो?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> लाई <xliff:g id="COUNT">^2</xliff:g> वटा भिडियो परिमार्जन गर्न दिने हो?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"सेफ्टी प्रोटेक्सन"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"नेटिभ ट्रान्स्कोड अलर्ट"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"नेटिभ ट्रान्स्कोड प्रोग्रेस"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"केही फोटोहरू लोड गर्न सकिँदैन"</string> + <string name="dialog_button_text" msgid="351366485240852280">"बुझेँ"</string> </resources> diff --git a/res/values-night-v31/styles.xml b/res/values-night-v31/styles.xml index 2a936f09a..58249be8a 100644 --- a/res/values-night-v31/styles.xml +++ b/res/values-night-v31/styles.xml @@ -14,7 +14,8 @@ limitations under the License. --> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <style name="PickerMaterialTheme" parent="@style/Theme.Material3.DayNight.NoActionBar"> <item name="materialAlertDialogTheme">@style/ProfileDialogTheme</item> @@ -40,6 +41,8 @@ <item name="pickerBannerPrimaryTextColor">?android:attr/textColorSecondary</item> <item name="pickerBannerSecondaryTextColor">?android:attr/textColorSecondary</item> <item name="pickerBannerButtonTextColor">@android:color/system_accent1_300</item> + <item name="categoryDefaultThumbnailColor">@android:color/system_accent1_300</item> + <item name="categoryDefaultThumbnailCircleColor">?androidprv:attr/materialColorSurfaceContainer</item> </style> </resources> diff --git a/res/values-night/styles.xml b/res/values-night/styles.xml index 72f234d1a..599ce12c1 100644 --- a/res/values-night/styles.xml +++ b/res/values-night/styles.xml @@ -14,7 +14,8 @@ limitations under the License. --> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <style name="PickerDialogTheme" parent="@android:style/Theme.DeviceDefault.Dialog.Alert"> @@ -59,6 +60,8 @@ <item name="pickerBannerPrimaryTextColor">?android:attr/textColorSecondary</item> <item name="pickerBannerSecondaryTextColor">?android:attr/textColorSecondary</item> <item name="pickerBannerButtonTextColor">?android:attr/colorAccent</item> + <item name="categoryDefaultThumbnailColor">?android:attr/colorAccent</item> + <item name="categoryDefaultThumbnailCircleColor">?androidprv:attr/materialColorSurfaceContainer</item> </style> </resources> diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 027622132..662a67926 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Lokale opslag"</string> <string name="app_label" msgid="9035307001052716210">"Mediaopslag"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Mediakiezer"</string> <string name="artist_label" msgid="8105600993099120273">"Artiest"</string> <string name="unknown" msgid="2059049215682829375">"Onbekend"</string> <string name="root_images" msgid="5861633549189045666">"Afbeeldingen"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Cloudmedia openen vanuit"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Geen"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Cloudmedia-app kan nu niet worden gewijzigd."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Mediakiezer"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Mediakiezer"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Media synchroniseren…"</string> <string name="add" msgid="2894574044585549298">"Toevoegen"</string> <string name="deselect" msgid="4297825044827769490">"Deselecteren"</string> <string name="deselected" msgid="8488133193326208475">"Gedeselecteerd"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Check de internetverbinding en probeer het opnieuw"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Opnieuw proberen"</string> <string name="not_selected" msgid="2244008151669896758">"niet geselecteerd"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Je geselecteerde media voorbereiden"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> van <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> klaar"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Nu ook met foto\'s waarvan een back-up is gemaakt"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Je kunt foto\'s selecteren uit het <xliff:g id="APP_NAME">%1$s</xliff:g>-account <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"App selecteren"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Account kiezen"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Account wijzigen"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Al je foto\'s ophalen"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> toestaan dit audiobestand aan te passen?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> toestaan <xliff:g id="COUNT">^2</xliff:g> audiobestanden aan te passen?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Audiobestand aanpassen…}other{<xliff:g id="COUNT">^1</xliff:g> audiobestanden aanpassen…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> toestaan deze video aan te passen?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> toestaan <xliff:g id="COUNT">^2</xliff:g> video\'s aan te passen?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Beveiliging"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Meldingen voor native transcodering"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Voortgang van native transcodering"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Kan bepaalde foto\'s niet laden"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index d9860112f..2c7c58e2c 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"ମିଡିଆ"</string> <string name="storage_description" msgid="4081716890357580107">"ଲୋକାଲ୍ ଷ୍ଟୋରେଜ୍"</string> <string name="app_label" msgid="9035307001052716210">"ମିଡିଆ ଷ୍ଟୋରେଜ୍"</string> - <string name="picker_app_label" msgid="4254039089502164761">"ମିଡିଆ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"ମିଡିଆ ପିକର"</string> <string name="artist_label" msgid="8105600993099120273">"କଳାକାର"</string> <string name="unknown" msgid="2059049215682829375">"ଅଜଣା"</string> <string name="root_images" msgid="5861633549189045666">"ଇମେଜ୍"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ଏଠାରୁ କ୍ଲାଉଡ ମିଡିଆକୁ ଆକ୍ସେସ କରନ୍ତୁ"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"କିଛି ନାହିଁ"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"ଏହି ସମୟରେ କ୍ଲାଉଡ ମିଡିଆ ଆପ ପରିବର୍ତ୍ତନ ହେଲା ନାହିଁ।"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"ମିଡିଆ ପିକର"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"ମିଡିଆ ପିକର"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"ମିଡିଆ ସିଙ୍କ କରାଯାଉଛି…"</string> <string name="add" msgid="2894574044585549298">"ଯୋଗ କରନ୍ତୁ"</string> <string name="deselect" msgid="4297825044827769490">"ଅଚୟନ କରନ୍ତୁ"</string> <string name="deselected" msgid="8488133193326208475">"ଅଚୟନ କରାଯାଇଛି"</string> @@ -56,14 +59,14 @@ <string name="picker_photos_empty_message" msgid="5980619500554575558">"କୌଣସି ଫଟୋ କିମ୍ବା ଭିଡିଓ ନାହିଁ"</string> <string name="picker_album_media_empty_message" msgid="7061850698189881671">"କୌଣସି ସମର୍ଥିତ ଫଟୋ କିମ୍ବା ଭିଡିଓ ନାହିଁ"</string> <string name="picker_albums_empty_message" msgid="8341079772950966815">"କୌଣସି ଆଲବମ ନାହିଁ"</string> - <string name="picker_view_selected" msgid="2266031384396143883">"ଚୟନିତଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ"</string> + <string name="picker_view_selected" msgid="2266031384396143883">"ଚୟନିତଗୁଡ଼ିକୁ ଭ୍ୟୁ କରନ୍ତୁ"</string> <string name="picker_photos" msgid="7415035516411087392">"ଫଟୋ"</string> <string name="picker_albums" msgid="4822511902115299142">"ଆଲବମ"</string> <string name="picker_preview" msgid="6257414886055861039">"ପ୍ରିଭ୍ୟୁ"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"ୱାର୍କକୁ ସ୍ୱିଚ୍ କରନ୍ତୁ"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"ବ୍ୟକ୍ତିଗତକୁ ସ୍ୱିଚ୍ କରନ୍ତୁ"</string> - <string name="picker_profile_admin_title" msgid="4172022376418293777">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ବ୍ଲକ୍ କରାଯାଇଛି"</string> - <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"କୌଣସି ବ୍ୟକ୍ତିଗତ ଆପରୁ ୱାର୍କ ଡାଟାକୁ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"ୱାର୍କକୁ ସୁଇଚ କରନ୍ତୁ"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"ବ୍ୟକ୍ତିଗତକୁ ସୁଇଚ କରନ୍ତୁ"</string> + <string name="picker_profile_admin_title" msgid="4172022376418293777">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ବ୍ଲକ କରାଯାଇଛି"</string> + <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"କୌଣସି ବ୍ୟକ୍ତିଗତ ଆପରୁ ୱାର୍କ ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"କୌଣସି ୱାର୍କ ଆପରୁ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"ୱାର୍କ ଆପଗୁଡ଼ିକୁ ବିରତ କରାଯାଇଛି"</string> <string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"ୱାର୍କ ଫଟୋଗୁଡ଼ିକୁ ଖୋଲିବାକୁ, ଆପଣଙ୍କ ୱାର୍କ ଆପଗୁଡ଼ିକୁ ଚାଲୁ କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ଆପଣଙ୍କ ଇଣ୍ଟରନେଟ କନେକ୍ସନ ଯାଞ୍ଚ କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="not_selected" msgid="2244008151669896758">"ଚୟନ କରାଯାଇନାହିଁ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"ଆପଣଙ୍କ ଚୟନିତ ମିଡିଆକୁ ପ୍ରସ୍ତୁତ କରାଯାଉଛି"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>ରୁ <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>ଟି ପ୍ରସ୍ତୁତ ଅଛି"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ବ୍ୟାକଅପ ନିଆଯାଇଥିବା ଫଟୋଗୁଡ଼ିକୁ ବର୍ତ୍ତମାନ ଅନ୍ତର୍ଭୁକ୍ତ କରାଯାଇଛି"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"ଆପଣ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆକାଉଣ୍ଟ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>ରୁ ଫଟୋଗୁଡ଼ିକୁ ଚୟନ କରିପାରିବେ"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ଆପ ବାଛନ୍ତୁ"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"ଆକାଉଣ୍ଟ ବାଛନ୍ତୁ"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ଆକାଉଣ୍ଟ ବଦଳାନ୍ତୁ"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"ଆପଣଙ୍କର ସମସ୍ତ ଫଟୋ ପ୍ରାପ୍ତ କରାଯାଉଛି"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{ଏହି ଅଡିଓ ଫାଇଲକୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ <xliff:g id="APP_NAME_0">^1</xliff:g>କୁ ଅନୁମତି ଦେବେ?}other{<xliff:g id="COUNT">^2</xliff:g>ଟି ଅଡିଓ ଫାଇଲକୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ <xliff:g id="APP_NAME_1">^1</xliff:g>କୁ ଅନୁମତି ଦେବେ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ଅଡିଓ ଫାଇଲ ପରିବର୍ତ୍ତନ କରାଯାଉଛି…}other{<xliff:g id="COUNT">^1</xliff:g>ଟି ଅଡିଓ ଫାଇଲ ପରିବର୍ତ୍ତନ କରାଯାଉଛି…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{ଏହି ଭିଡିଓକୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ <xliff:g id="APP_NAME_0">^1</xliff:g>କୁ ଅନୁମତି ଦେବେ?}other{<xliff:g id="COUNT">^2</xliff:g>ଟି ଭିଡିଓକୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ <xliff:g id="APP_NAME_1">^1</xliff:g>କୁ ଅନୁମତି ଦେବେ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"ସୁରକ୍ଷିତ ସୁରକ୍ଷା"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"ନେଟିଭ ଟ୍ରାନ୍ସକୋଡ ଆଲର୍ଟ"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"ନେଟିଭ ଟ୍ରାନ୍ସକୋଡ ପ୍ରୋଗ୍ରେସ"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"କିଛି ଫଟୋ ଲୋଡ କରାଯାଇପାରିବ ନାହିଁ"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ବୁଝିଗଲି"</string> </resources> diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index fda3c9452..859b3106f 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"ਮੀਡੀਆ"</string> <string name="storage_description" msgid="4081716890357580107">"ਸਥਾਨਕ ਸਟੋਰੇਜ"</string> <string name="app_label" msgid="9035307001052716210">"ਮੀਡੀਆ ਸਟੋਰੇਜ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"ਮੀਡੀਆ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"ਮੀਡੀਆ ਚੋਣਕਾਰ"</string> <string name="artist_label" msgid="8105600993099120273">"ਕਲਾਕਾਰ"</string> <string name="unknown" msgid="2059049215682829375">"ਅਗਿਆਤ"</string> <string name="root_images" msgid="5861633549189045666">"ਚਿੱਤਰ"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"ਇੱਥੋਂ ਕਲਾਊਡ ਮੀਡੀਆ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ਕੋਈ ਨਹੀਂ"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"ਇਸ ਸਮੇਂ ਕਲਾਊਡ ਮੀਡੀਆ ਐਪ ਨੂੰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ।"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"ਮੀਡੀਆ ਚੋਣਕਾਰ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"ਮੀਡੀਆ ਚੋਣਕਾਰ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"ਮੀਡੀਆ ਸਿੰਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string> <string name="add" msgid="2894574044585549298">"ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="deselect" msgid="4297825044827769490">"ਅਣ-ਚੁਣਿਆ ਕਰੋ"</string> <string name="deselected" msgid="8488133193326208475">"ਅਣ-ਚੁਣਿਆ"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ਆਪਣੇ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਦੀ ਜਾਂਚ ਕਰ ਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="not_selected" msgid="2244008151669896758">"ਚੁਣਿਆ ਨਹੀਂ ਗਿਆ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"ਤੁਹਾਡਾ ਚੁਣਿਆ ਗਿਆ ਮੀਡੀਆ ਤਿਆਰ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ਵਿੱਚੋਂ <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> ਤਿਆਰ"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"ਬੈਕਅੱਪ ਕੀਤੀਆਂ ਫ਼ੋਟੋਆਂ ਨੂੰ ਹੁਣ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"ਤੁਸੀਂ ਖਾਤੇ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> ਦੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਵਿੱਚੋਂ ਫ਼ੋਟੋਆਂ ਨੂੰ ਚੁਣੋ"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"ਤੁਸੀਂ <xliff:g id="APP_NAME">%1$s</xliff:g> ਵਿੱਚੋਂ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> ਖਾਤੇ ਤੋਂ ਫ਼ੋਟੋਆਂ ਚੁਣ ਸਕਦੇ ਹੋ"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਖਾਤੇ ਨੂੰ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"<xliff:g id="USER_ACCOUNT">%1$s</xliff:g> ਦੀਆਂ ਫ਼ੋਟੋਆਂ ਨੂੰ ਹੁਣ ਇੱਥੇ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"ਕਲਾਊਡ ਮੀਡੀਆ ਐਪ ਨੂੰ ਚੁਣੋ"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ਐਪ ਚੁਣੋ"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"ਖਾਤਾ ਚੁਣੋ"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ਖਾਤਾ ਬਦਲੋ"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"ਤੁਹਾਡੀਆਂ ਸਾਰੀਆਂ ਫ਼ੋਟੋਆਂ ਪ੍ਰਾਪਤ ਕੀਤੀਆਂ ਜਾ ਰਹੀਆਂ ਹਨ"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{ਕੀ <xliff:g id="APP_NAME_0">^1</xliff:g> ਨੂੰ ਇਸ ਆਡੀਓ ਫ਼ਾਈਲ ਨੂੰ ਸੋਧਣ ਦੇਣਾ ਹੈ?}one{ਕੀ <xliff:g id="APP_NAME_1">^1</xliff:g> ਨੂੰ <xliff:g id="COUNT">^2</xliff:g> ਆਡੀਓ ਫ਼ਾਈਲ ਨੂੰ ਸੋਧਣ ਦੇਣਾ ਹੈ?}other{ਕੀ <xliff:g id="APP_NAME_1">^1</xliff:g> ਨੂੰ <xliff:g id="COUNT">^2</xliff:g> ਆਡੀਓ ਫ਼ਾਈਲਾਂ ਨੂੰ ਸੋਧਣ ਦੇਣਾ ਹੈ?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ਆਡੀਓ ਫ਼ਾਈਲ ਸੋਧੀ ਜਾ ਰਹੀ ਹੈ…}one{<xliff:g id="COUNT">^1</xliff:g> ਆਡੀਓ ਫ਼ਾਈਲ ਸੋਧੀ ਜਾ ਰਹੀ ਹੈ…}other{<xliff:g id="COUNT">^1</xliff:g> ਆਡੀਓ ਫ਼ਾਈਲਾਂ ਸੋਧੀਆਂ ਜਾ ਰਹੀਆਂ ਹਨ…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{ਕੀ <xliff:g id="APP_NAME_0">^1</xliff:g> ਨੂੰ ਇਸ ਵੀਡੀਓ ਨੂੰ ਸੋਧਣ ਦੇਣਾ ਹੈ?}one{ਕੀ <xliff:g id="APP_NAME_1">^1</xliff:g> ਨੂੰ <xliff:g id="COUNT">^2</xliff:g> ਵੀਡੀਓ ਨੂੰ ਸੋਧਣ ਦੇਣਾ ਹੈ?}other{ਕੀ <xliff:g id="APP_NAME_1">^1</xliff:g> ਨੂੰ <xliff:g id="COUNT">^2</xliff:g> ਵੀਡੀਓ ਨੂੰ ਸੋਧਣ ਦੇਣਾ ਹੈ?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"ਸੁਰੱਖਿਆ ਬਚਾਅ"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"ਨੇਟਿਵ ਟ੍ਰਾਂਸਕੋਡ ਸੁਚੇਤਨਾਵਾਂ"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"ਨੇਟਿਵ ਟ੍ਰਾਂਸਕੋਡ ਪ੍ਰਗਤੀ"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"ਕੁਝ ਫ਼ੋਟੋਆਂ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ਸਮਝ ਲਿਆ"</string> </resources> diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 2cd3119e3..8d3604163 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimedia"</string> <string name="storage_description" msgid="4081716890357580107">"Pamięć lokalna"</string> <string name="app_label" msgid="9035307001052716210">"Przechowywanie multimediów"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Multimedia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Wybór mediów"</string> <string name="artist_label" msgid="8105600993099120273">"Wykonawca"</string> <string name="unknown" msgid="2059049215682829375">"Nieznany"</string> <string name="root_images" msgid="5861633549189045666">"Obrazy"</string> @@ -46,10 +46,13 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Otwieraj multimedia w chmurze za pomocą:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Brak"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Nie udało się zmienić aplikacji do multimediów w chmurze."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Wybór mediów"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Wybór mediów"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synchronizuję multimedia…"</string> <string name="add" msgid="2894574044585549298">"Dodaj"</string> - <string name="deselect" msgid="4297825044827769490">"Odznacz"</string> + <string name="deselect" msgid="4297825044827769490">"Usuń wybór"</string> <string name="deselected" msgid="8488133193326208475">"Usunięto wybór"</string> - <string name="select" msgid="2704765470563027689">"Zaznacz"</string> + <string name="select" msgid="2704765470563027689">"Wybierz"</string> <string name="selected" msgid="9151797369975828124">"Wybrano"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{Wybierz maksymalnie <xliff:g id="COUNT_0">^1</xliff:g> element}few{Wybierz maksymalnie <xliff:g id="COUNT_1">^1</xliff:g> elementy}many{Wybierz maksymalnie <xliff:g id="COUNT_1">^1</xliff:g> elementów}other{Wybierz maksymalnie <xliff:g id="COUNT_1">^1</xliff:g> elementu}}"</string> <string name="recent" msgid="6694613584743207874">"Ostatnie"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Sprawdź połączenie z internetem i spróbuj ponownie"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Ponów"</string> <string name="not_selected" msgid="2244008151669896758">"nie wybrano"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Przygotowywanie wybranych multimediów"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Gotowe <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> z <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Teraz znajdziesz tu kopie zapasowe zdjęć"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Możesz wybrać zdjęcia z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>, z konta <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Wybierz aplikację"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Wybierz konto"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Zmień konto"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Pobieram wszystkie Twoje zdjęcia"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Zezwolić aplikacji <xliff:g id="APP_NAME_0">^1</xliff:g> na zmodyfikowanie tego pliku audio?}few{Zezwolić aplikacji <xliff:g id="APP_NAME_1">^1</xliff:g> na zmodyfikowanie <xliff:g id="COUNT">^2</xliff:g> plików audio?}many{Zezwolić aplikacji <xliff:g id="APP_NAME_1">^1</xliff:g> na zmodyfikowanie <xliff:g id="COUNT">^2</xliff:g> plików audio?}other{Zezwolić aplikacji <xliff:g id="APP_NAME_1">^1</xliff:g> na zmodyfikowanie <xliff:g id="COUNT">^2</xliff:g> pliku audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modyfikuję plik audio…}few{Modyfikuję <xliff:g id="COUNT">^1</xliff:g> pliki audio…}many{Modyfikuję <xliff:g id="COUNT">^1</xliff:g> plików audio…}other{Modyfikuję <xliff:g id="COUNT">^1</xliff:g> pliku audio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Zezwolić aplikacji <xliff:g id="APP_NAME_0">^1</xliff:g> na zmodyfikowanie tego filmu?}few{Zezwolić aplikacji <xliff:g id="APP_NAME_1">^1</xliff:g> na zmodyfikowanie <xliff:g id="COUNT">^2</xliff:g> filmów?}many{Zezwolić aplikacji <xliff:g id="APP_NAME_1">^1</xliff:g> na zmodyfikowanie <xliff:g id="COUNT">^2</xliff:g> filmów?}other{Zezwolić aplikacji <xliff:g id="APP_NAME_1">^1</xliff:g> na zmodyfikowanie <xliff:g id="COUNT">^2</xliff:g> filmu?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Sprzęt zabezpieczający"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alerty dotyczące transkodowania natywnego"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Postępy transkodowania natywnego"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Nie można wczytać niektórych zdjęć"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index 76b2e27ca..3c02de6ea 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Mídia"</string> <string name="storage_description" msgid="4081716890357580107">"Armazenamento local"</string> <string name="app_label" msgid="9035307001052716210">"Armazenamento de mídia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Mídia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Seletor de mídia"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Desconhecido"</string> <string name="root_images" msgid="5861633549189045666">"Imagens"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Acessar a mídia em nuvem de"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Nenhum"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Não foi possível mudar o app de mídia em nuvem."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Seletor de mídia"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Seletor de mídia"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sincronizando mídia…"</string> <string name="add" msgid="2894574044585549298">"Adicionar"</string> <string name="deselect" msgid="4297825044827769490">"Desmarcar"</string> <string name="deselected" msgid="8488133193326208475">"Desmarcada"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Fotos"</string> <string name="picker_albums" msgid="4822511902115299142">"Álbuns"</string> <string name="picker_preview" msgid="6257414886055861039">"Visualização"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Mudar para \"Trabalho\""</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Mudar para \"Pessoal\""</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Mudar para Trabalho"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Mudar para Pessoal"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Bloqueado pelo administrador"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Não é permitido o acesso a dados de trabalho em um app pessoal"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Não é permitido o acesso a dados pessoais em um app de trabalho"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Confira sua conexão de Internet e tente de novo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Tentar novamente"</string> <string name="not_selected" msgid="2244008151669896758">"não selecionado"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparando a mídia selecionada"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> de <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> itens prontos"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Fotos salvas em backup agora estão incluídas"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"As fotos salvas em backup agora estão incluídas"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Selecione fotos da conta <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> do app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"A conta do app <xliff:g id="APP_NAME">%1$s</xliff:g> foi atualizada"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"As fotos da conta <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> agora estão incluídas aqui"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Selecionar app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Escolher conta"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Trocar conta"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Acessando todas as suas fotos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Permitir que o app <xliff:g id="APP_NAME_0">^1</xliff:g> modifique esse arquivo de áudio?}one{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> arquivo de áudio?}many{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> arquivos de áudio?}other{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> arquivos de áudio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modificando o arquivo de áudio…}one{Modificando <xliff:g id="COUNT">^1</xliff:g> arquivo de áudio…}many{Modificando <xliff:g id="COUNT">^1</xliff:g> arquivos de áudio…}other{Modificando <xliff:g id="COUNT">^1</xliff:g> arquivos de áudio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Permitir que o app <xliff:g id="APP_NAME_0">^1</xliff:g> modifique esse vídeo?}one{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeo?}many{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}other{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Proteção"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertas da transcodificação nativa"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progresso da transcodificação nativa"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Não é possível carregar algumas fotos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Entendi"</string> </resources> diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index eb9f0b48d..7e6a292fd 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimédia"</string> <string name="storage_description" msgid="4081716890357580107">"Armazenamento local"</string> <string name="app_label" msgid="9035307001052716210">"Armazenamento de multimédia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Multimédia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Seletor de meios"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Desconhecido"</string> <string name="root_images" msgid="5861633549189045666">"Imagens"</string> @@ -46,8 +46,11 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Aceda a multimédia na nuvem a partir de"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Nenhuma"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Impossível alterar a app de multimédia na nuvem."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Seletor de meios"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Seletor de meios"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"A sincronizar conteúdo multimédia…"</string> <string name="add" msgid="2894574044585549298">"Adicionar"</string> - <string name="deselect" msgid="4297825044827769490">"Desselecionar"</string> + <string name="deselect" msgid="4297825044827769490">"Desmarcar"</string> <string name="deselected" msgid="8488133193326208475">"Desmarcado"</string> <string name="select" msgid="2704765470563027689">"Selecionar"</string> <string name="selected" msgid="9151797369975828124">"Selecionado"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Verifique a ligação à Internet e tente novamente"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Tentar novamente"</string> <string name="not_selected" msgid="2244008151669896758">"não selecionado"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"A preparar conteúdo multimédia selecionado"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> de <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> item(ns) pronto(s)"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"As fotos com cópia de segurança já estão incluídas"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Pode selecionar fotos da app <xliff:g id="APP_NAME">%1$s</xliff:g> da conta <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Escolher app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Escolher conta"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Alterar conta"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"A obter todas as suas fotos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Permitir que a app <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este ficheiro de áudio?}many{Permitir que a app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> ficheiros de áudio?}other{Permitir que a app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> ficheiros de áudio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{A modificar o ficheiro de áudio…}many{A modificar <xliff:g id="COUNT">^1</xliff:g> ficheiro(s) de áudio…}other{A modificar <xliff:g id="COUNT">^1</xliff:g> ficheiro(s) de áudio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Permitir que a app <xliff:g id="APP_NAME_0">^1</xliff:g> modifique este vídeo?}many{Permitir que a app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}other{Permitir que a app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}}"</string> @@ -149,4 +154,7 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Proteção de segurança"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertas de transcodificação nativa"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progresso de transcodificação nativa"</string> + <string name="dialog_error_message" msgid="5120432204743681606">"Tente mais tarde. As suas fotos vão estar disponíveis quando o problema estiver resolvido."</string> + <string name="dialog_error_title" msgid="636349284077820636">"Não é possível carregar algumas fotos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 76b2e27ca..3c02de6ea 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Mídia"</string> <string name="storage_description" msgid="4081716890357580107">"Armazenamento local"</string> <string name="app_label" msgid="9035307001052716210">"Armazenamento de mídia"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Mídia"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Seletor de mídia"</string> <string name="artist_label" msgid="8105600993099120273">"Artista"</string> <string name="unknown" msgid="2059049215682829375">"Desconhecido"</string> <string name="root_images" msgid="5861633549189045666">"Imagens"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Acessar a mídia em nuvem de"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Nenhum"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Não foi possível mudar o app de mídia em nuvem."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Seletor de mídia"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Seletor de mídia"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sincronizando mídia…"</string> <string name="add" msgid="2894574044585549298">"Adicionar"</string> <string name="deselect" msgid="4297825044827769490">"Desmarcar"</string> <string name="deselected" msgid="8488133193326208475">"Desmarcada"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Fotos"</string> <string name="picker_albums" msgid="4822511902115299142">"Álbuns"</string> <string name="picker_preview" msgid="6257414886055861039">"Visualização"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Mudar para \"Trabalho\""</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Mudar para \"Pessoal\""</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Mudar para Trabalho"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Mudar para Pessoal"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Bloqueado pelo administrador"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Não é permitido o acesso a dados de trabalho em um app pessoal"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Não é permitido o acesso a dados pessoais em um app de trabalho"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Confira sua conexão de Internet e tente de novo"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Tentar novamente"</string> <string name="not_selected" msgid="2244008151669896758">"não selecionado"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Preparando a mídia selecionada"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> de <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> itens prontos"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Fotos salvas em backup agora estão incluídas"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"As fotos salvas em backup agora estão incluídas"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Selecione fotos da conta <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> do app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"A conta do app <xliff:g id="APP_NAME">%1$s</xliff:g> foi atualizada"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"As fotos da conta <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> agora estão incluídas aqui"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Selecionar app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Escolher conta"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Trocar conta"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Acessando todas as suas fotos"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Permitir que o app <xliff:g id="APP_NAME_0">^1</xliff:g> modifique esse arquivo de áudio?}one{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> arquivo de áudio?}many{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> arquivos de áudio?}other{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> arquivos de áudio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Modificando o arquivo de áudio…}one{Modificando <xliff:g id="COUNT">^1</xliff:g> arquivo de áudio…}many{Modificando <xliff:g id="COUNT">^1</xliff:g> arquivos de áudio…}other{Modificando <xliff:g id="COUNT">^1</xliff:g> arquivos de áudio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Permitir que o app <xliff:g id="APP_NAME_0">^1</xliff:g> modifique esse vídeo?}one{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeo?}many{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}other{Permitir que o app <xliff:g id="APP_NAME_1">^1</xliff:g> modifique <xliff:g id="COUNT">^2</xliff:g> vídeos?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Proteção"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alertas da transcodificação nativa"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progresso da transcodificação nativa"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Não é possível carregar algumas fotos"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Entendi"</string> </resources> diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index 7682e076f..f0b12d141 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Conținut media"</string> <string name="storage_description" msgid="4081716890357580107">"Stocare locală"</string> <string name="app_label" msgid="9035307001052716210">"Stocarea conținutului media"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Selector de suport"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Necunoscut"</string> <string name="root_images" msgid="5861633549189045666">"Imagini"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Accesează conținutul media în cloud din"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Niciuna"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Nu s-a putut schimba aplicația media pentru cloud"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Selector de suport"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Selector de suport"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Se sincronizează conținutul media…"</string> <string name="add" msgid="2894574044585549298">"Adaugă"</string> <string name="deselect" msgid="4297825044827769490">"Debifează"</string> <string name="deselected" msgid="8488133193326208475">"Deselectat"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Verifică-ți conexiunea la internet și încearcă din nou"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Încearcă din nou"</string> <string name="not_selected" msgid="2244008151669896758">"neselectat"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Se pregătește conținutul media selectat"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Finalizate: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> din <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Fotografiile cu backup sunt incluse acum"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Poți selecta fotografii din contul <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Alege aplicația"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Alege un cont"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Schimbă contul"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Se încarcă toate fotografiile"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Permiți ca <xliff:g id="APP_NAME_0">^1</xliff:g> să modifice acest fișier audio?}few{Permiți ca <xliff:g id="APP_NAME_1">^1</xliff:g> să modifice <xliff:g id="COUNT">^2</xliff:g> fișiere audio?}other{Permiți ca <xliff:g id="APP_NAME_1">^1</xliff:g> să modifice <xliff:g id="COUNT">^2</xliff:g> de fișiere audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Se modifică fișierul audio…}few{Se modifică <xliff:g id="COUNT">^1</xliff:g> fișiere audio…}other{Se modifică <xliff:g id="COUNT">^1</xliff:g> de fișiere audio…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Permiți ca <xliff:g id="APP_NAME_0">^1</xliff:g> să modifice acest videoclip?}few{Permiți ca <xliff:g id="APP_NAME_1">^1</xliff:g> să modifice <xliff:g id="COUNT">^2</xliff:g> videoclipuri?}other{Permiți ca <xliff:g id="APP_NAME_1">^1</xliff:g> să modifice <xliff:g id="COUNT">^2</xliff:g> de videoclipuri?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Protecția în caz de accidente"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Alerte privind transcodarea în codul nativ"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progresul transcodării în codul nativ"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Unele fotografii nu pot fi încărcate"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 25d46684a..0b212b7c1 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Мультимедиа"</string> <string name="storage_description" msgid="4081716890357580107">"Локальное хранилище"</string> <string name="app_label" msgid="9035307001052716210">"Хранилище мультимедиа"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Мультимедиа"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Инструмент выбора медиа"</string> <string name="artist_label" msgid="8105600993099120273">"Исполнитель"</string> <string name="unknown" msgid="2059049215682829375">"Неизвестно"</string> <string name="root_images" msgid="5861633549189045666">"Изображения"</string> @@ -43,9 +43,12 @@ <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Приложение для мультимедиа в облаке"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Приложение для мультимедиа в облаке"</string> <string name="picker_settings_description" msgid="2916686824777214585">"Выбирайте свои фото и видео из облака в приложениях или на сайтах."</string> - <string name="picker_settings_selection_message" msgid="245453573086488596">"Получите доступ к мультимедиа в облаке"</string> + <string name="picker_settings_selection_message" msgid="245453573086488596">"Какое приложение использовать для доступа к медиафайлам в облаке?"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Нет"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Не удалось изменить приложение для мультимедиа."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Инструмент выбора медиа"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Инструмент выбора медиа"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Синхронизация медиаконтента…"</string> <string name="add" msgid="2894574044585549298">"Добавить"</string> <string name="deselect" msgid="4297825044827769490">"Отменить выбор"</string> <string name="deselected" msgid="8488133193326208475">"Выбор отменен"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Проверьте подключение к интернету и повторите попытку."</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Повторить"</string> <string name="not_selected" msgid="2244008151669896758">"не выбрано"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Подготовка выбранных медиафайлов"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Предзагрузка: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> из <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Резервные копии фотографий добавлены"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Теперь можно выбирать фотографии в облаке"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Вы можете выбрать фотографии из аккаунта <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g>: аккаунт обновлен"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Фотографии из аккаунта <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> теперь хранятся здесь."</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Выбрать приложение"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Выбрать аккаунт"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Сменить аккаунт"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Ваши фотографии загружаются"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Разрешить приложению \"<xliff:g id="APP_NAME_0">^1</xliff:g>\" изменить этот аудиофайл?}one{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> аудиофайл?}few{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> аудиофайла?}many{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> аудиофайлов?}other{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> аудиофайла?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Изменение аудиофайла…}one{Изменение <xliff:g id="COUNT">^1</xliff:g> аудиофайла…}few{Изменение <xliff:g id="COUNT">^1</xliff:g> аудиофайлов…}many{Изменение <xliff:g id="COUNT">^1</xliff:g> аудиофайлов…}other{Изменение <xliff:g id="COUNT">^1</xliff:g> аудиофайла…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Разрешить приложению \"<xliff:g id="APP_NAME_0">^1</xliff:g>\" изменить это видео?}one{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> видео?}few{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> видео?}many{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> видео?}other{Разрешить приложению \"<xliff:g id="APP_NAME_1">^1</xliff:g>\" изменить <xliff:g id="COUNT">^2</xliff:g> видео?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Защита безопасности"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Уведомления нативного перекодирования"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Прогресс нативного перекодирования"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Не удается загрузить некоторые фотографии"</string> + <string name="dialog_button_text" msgid="351366485240852280">"ОК"</string> </resources> diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index c339669a6..9ed5bd18e 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"මාධ්ය"</string> <string name="storage_description" msgid="4081716890357580107">"පෙදෙසි ආචයනය"</string> <string name="app_label" msgid="9035307001052716210">"මාධ්ය ගබඩාව"</string> - <string name="picker_app_label" msgid="4254039089502164761">"මාධ්ය"</string> + <string name="picker_app_label" msgid="1195424381053599122">"මාධ්ය තෝරනය"</string> <string name="artist_label" msgid="8105600993099120273">"කලාකරු"</string> <string name="unknown" msgid="2059049215682829375">"නොදනී"</string> <string name="root_images" msgid="5861633549189045666">"රූප"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"මෙයින් ක්ලවුඩ් මාධ්ය වෙත ප්රවේශ වන්න"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"කිසිවක් නැත"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"මෙම අවස්ථාවේ ක්ලවුඩ් මාධ්ය යෙදුම වෙනස් කළ නොහැක."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"මාධ්ය තෝරනය"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"මාධ්ය තෝරනය"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"මාධ්ය සමමුහුර්ත කරමින්…"</string> <string name="add" msgid="2894574044585549298">"එක් කරන්න"</string> <string name="deselect" msgid="4297825044827769490">"නොතෝරන්න"</string> <string name="deselected" msgid="8488133193326208475">"නොතෝරන ලද"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ඔබේ අන්තර්ජාල සබැඳුම පරීක්ෂා කර නැවත උත්සාහ කරන්න"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"යළි උත්සාහ කරන්න"</string> <string name="not_selected" msgid="2244008151669896758">"තෝරා නොමැත"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"ඔබ තෝරන ලද මාධ්ය සූදානම් කරමින්"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>කින් <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>ක් සූදානම්"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"උපස්ථ කළ ඡායාරූප දැන් ඇතුළත් කර ඇත"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"ඔබට <xliff:g id="APP_NAME">%1$s</xliff:g> ගිණුමෙන් <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> ඡායාරූප තෝරා ගත හැක"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"යෙදුම තෝරා ගන්න"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"ගිණුම තෝරා ගන්න"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ගිණුම වෙනස් කරන්න"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"ඔබේ සියලු ඡායාරූප ලබා ගැනීම"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> හට මෙම ශ්රව්ය ගොනුව වෙනස් කිරීමට ඉඩ දෙන්නද?}one{<xliff:g id="APP_NAME_1">^1</xliff:g> හට ශ්රව්ය ගොනු <xliff:g id="COUNT">^2</xliff:g>ක් වෙනස් කිරීමට ඉඩ දෙන්නද?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> හට ශ්රව්ය ගොනු <xliff:g id="COUNT">^2</xliff:g>ක් වෙනස් කිරීමට ඉඩ දෙන්නද?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ශ්රව්ය ගොනුව වෙනස් කරමින්…}one{ශ්රව්ය ගොනු <xliff:g id="COUNT">^1</xliff:g>ක් වෙනස් කරමින්…}other{ශ්රව්ය ගොනු <xliff:g id="COUNT">^1</xliff:g>ක් වෙනස් කරමින්…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> හට මෙම වීඩියෝව වෙනස් කිරීමට ඉඩ දෙන්නද?}one{<xliff:g id="APP_NAME_1">^1</xliff:g> හට වීඩියෝ <xliff:g id="COUNT">^2</xliff:g>ක් වෙනස් කිරීමට ඉඩ දෙන්නද?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> හට වීඩියෝ <xliff:g id="COUNT">^2</xliff:g>ක් වෙනස් කිරීමට ඉඩ දෙන්නද?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"සුරක්ෂිතතා ආරක්ෂණය"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"සහජ ට්රාන්ස්කෝඩ් ඇඟවීම්"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"සහජ ට්රාන්ස්කෝඩ් ප්රගතිය"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"සමහර ඡායාරූප පූරණය කළ නොහැක"</string> + <string name="dialog_button_text" msgid="351366485240852280">"තේරුණා"</string> </resources> diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 80eebfc73..def0ce037 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Médiá"</string> <string name="storage_description" msgid="4081716890357580107">"Miestne úložisko"</string> <string name="app_label" msgid="9035307001052716210">"Úložisko médií"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Médiá"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Nástroj na výber médií"</string> <string name="artist_label" msgid="8105600993099120273">"Interpret"</string> <string name="unknown" msgid="2059049215682829375">"Neznáme"</string> <string name="root_images" msgid="5861633549189045666">"Obrázky"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Získavať prístup k médiám v cloude v aplikácii"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Žiadne"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Momentálne sa nepodarilo zmeniť cloudový prehrávač"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Nástroj na výber médií"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Nástroj na výber médií"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synchronizujú sa médiá…"</string> <string name="add" msgid="2894574044585549298">"Pridať"</string> <string name="deselect" msgid="4297825044827769490">"Zrušiť výber"</string> <string name="deselected" msgid="8488133193326208475">"Výber bol zrušený"</string> @@ -60,14 +63,14 @@ <string name="picker_photos" msgid="7415035516411087392">"Fotky"</string> <string name="picker_albums" msgid="4822511902115299142">"Albumy"</string> <string name="picker_preview" msgid="6257414886055861039">"Ukážka"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Prepnúť na pracovný"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Prepnúť na osobný"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Prepnúť na pracovný profil"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Prepnúť na osobný profil"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Blokované vaším správcom"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Prístup k pracovným údajom z osobnej aplikácie nie je povolený"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Prístup k osobným údajom z pracovnej aplikácie nie je povolený"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"Pracovné aplikácie sú pozastavené"</string> <string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"Ak chcete otvoriť pracovné fotky, zapnite pracovné aplikácie a skúste to znova"</string> - <string name="picker_privacy_message" msgid="9132700451027116817">"Táto aplikácia môže mať prístup iba k fotkám, ktoré vyberiete"</string> + <string name="picker_privacy_message" msgid="9132700451027116817">"Táto aplikácia má prístup iba k fotkám, ktoré vyberiete"</string> <string name="picker_header_permissions" msgid="675872774407768495">"Vyberte fotky a videá, ku ktorým má mať táto aplikácia prístup"</string> <string name="picker_album_item_count" msgid="4420723302534177596">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> položka}few{<xliff:g id="COUNT_1">^1</xliff:g> položky}many{<xliff:g id="COUNT_1">^1</xliff:g> items}other{<xliff:g id="COUNT_1">^1</xliff:g> položiek}}"</string> <string name="picker_add_button_multi_select" msgid="4005164092275518399">"Pridať (<xliff:g id="COUNT">^1</xliff:g>)"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Skontrolujte internetové pripojenie a skúste to znova"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Skúsiť znova"</string> <string name="not_selected" msgid="2244008151669896758">"nevybrané"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Pripravujú sa vybrané médiá"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Pripravené: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> z <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Zálohované fotky sú teraz zahrnuté"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Môžete vybrať fotky z účtu <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Vybrať aplikáciu"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Vybrať účet"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Zmeniť účet"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Načítavajú sa všekty vaše fotky"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Chcete povoliť aplikácii <xliff:g id="APP_NAME_0">^1</xliff:g> upraviť tento zvukový súbor?}few{Chcete povoliť aplikácii <xliff:g id="APP_NAME_1">^1</xliff:g> upraviť <xliff:g id="COUNT">^2</xliff:g> zvukové súbory?}many{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> audio files?}other{Chcete povoliť aplikácii <xliff:g id="APP_NAME_1">^1</xliff:g> upraviť <xliff:g id="COUNT">^2</xliff:g> zvukových súborov?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Upravuje sa zvukový súbor…}few{Upravujú sa <xliff:g id="COUNT">^1</xliff:g> zvukové súbory…}many{Modifying <xliff:g id="COUNT">^1</xliff:g> audio files…}other{Upravuje sa <xliff:g id="COUNT">^1</xliff:g> zvukových súborov…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Chcete povoliť aplikácii <xliff:g id="APP_NAME_0">^1</xliff:g> upraviť toto video?}few{Chcete povoliť aplikácii <xliff:g id="APP_NAME_1">^1</xliff:g> upraviť <xliff:g id="COUNT">^2</xliff:g> videá?}many{Allow <xliff:g id="APP_NAME_1">^1</xliff:g> to modify <xliff:g id="COUNT">^2</xliff:g> videos?}other{Chcete povoliť aplikácii <xliff:g id="APP_NAME_1">^1</xliff:g> upraviť <xliff:g id="COUNT">^2</xliff:g> videí?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Bezpečnosť"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Upozornenia natívneho prekódovania"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Postup natívneho prekódovania"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Niektoré fotky sa nedajú načítať"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Dobre"</string> </resources> diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 0f7e3806b..aca8523e0 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Predstavnost"</string> <string name="storage_description" msgid="4081716890357580107">"Lokalna shramba"</string> <string name="app_label" msgid="9035307001052716210">"Shramba za predstavnost"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Predstavnost"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Orodje za izbiranje predstavnosti"</string> <string name="artist_label" msgid="8105600993099120273">"Izvajalec"</string> <string name="unknown" msgid="2059049215682829375">"Neznano"</string> <string name="root_images" msgid="5861633549189045666">"Slike"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Dostop do predstavnosti v oblaku v storitvi"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Brez"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Zamenjava aplikacije za predstavnost v oblaku trenutno ni mogoča."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Orodje za izbiranje predstavnosti"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Orodje za izbiranje predstavnosti"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sinhroniziranje predstavnosti …"</string> <string name="add" msgid="2894574044585549298">"Dodaj"</string> <string name="deselect" msgid="4297825044827769490">"Počisti izbiro"</string> <string name="deselected" msgid="8488133193326208475">"Izbor je preklican"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Preverite internetno povezavo in poskusite znova."</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Poskusi znova"</string> <string name="not_selected" msgid="2244008151669896758">"ni izbrano"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Pripravljanje izbranih predstavnostnih vsebin"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Pripravljenih: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> od <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Varnostno kopirane fotografije so zdaj vključene"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Izberete lahko fotografije iz računa <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Izbira aplikacije"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Izbira računa"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Sprememba računa"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Pridobivanje vseh vaših fotografij"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_0">^1</xliff:g>, da spremeni to zvočno datoteko?}one{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> zvočno datoteko?}two{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> zvočni datoteki?}few{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> zvočne datoteke?}other{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> zvočnih datotek?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Spreminjanje zvočne datoteke …}one{Spreminjanje <xliff:g id="COUNT">^1</xliff:g> zvočne datoteke …}two{Spreminjanje <xliff:g id="COUNT">^1</xliff:g> zvočnih datotek …}few{Spreminjanje <xliff:g id="COUNT">^1</xliff:g> zvočnih datotek …}other{Spreminjanje <xliff:g id="COUNT">^1</xliff:g> zvočnih datotek …}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_0">^1</xliff:g>, da spremeni ta videoposnetek?}one{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> videoposnetek?}two{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> videoposnetka?}few{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> videoposnetke?}other{Želite dovoliti aplikaciji <xliff:g id="APP_NAME_1">^1</xliff:g>, da spremeni <xliff:g id="COUNT">^2</xliff:g> videoposnetkov?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Varnostna zaščita"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Opozorila o izvornem prekodiranju"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Napredek izvornega prekodiranja"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Nekaterih fotografij ni mogoče naložiti"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Razumem"</string> </resources> diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index ff2a35d53..51376e486 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Hapësira ruajtëse lokale"</string> <string name="app_label" msgid="9035307001052716210">"Hapësira ruajtëse e medias"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Zgjedhësi i medias"</string> <string name="artist_label" msgid="8105600993099120273">"Artisti"</string> <string name="unknown" msgid="2059049215682829375">"I panjohur"</string> <string name="root_images" msgid="5861633549189045666">"Fotografitë"</string> @@ -42,10 +42,13 @@ <string name="picker_settings" msgid="6443463167344790260">"Aplikacioni i medias në renë kompjuterike"</string> <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Aplikacion i medias në renë kompjuterike"</string> <string name="picker_settings_title" msgid="5647700706470673258">"Aplikacioni i medias në renë kompjuterike"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Qasu te media jote në renë kompjuterike kur një aplikacion ose sajt uebi të kërkon të zgjedhësh fotografitë ose videot"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Qasu te media jote në renë kompjuterike kur një aplikacion ose uebsajt të kërkon të zgjedhësh fotografitë ose videot"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Qasu te media në renë kompjuterike nga"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Asnjë"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Aplikacioni i medias në renë kompjuterike nuk mund të ndryshohej në këtë moment."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Zgjedhësi i medias"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Zgjedhësi i medias"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Media po sinkronizohet…"</string> <string name="add" msgid="2894574044585549298">"Shto"</string> <string name="deselect" msgid="4297825044827769490">"Hiq përzgjedhjen"</string> <string name="deselected" msgid="8488133193326208475">"Zgjedhja është hequr"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Fotografitë"</string> <string name="picker_albums" msgid="4822511902115299142">"Albumet"</string> <string name="picker_preview" msgid="6257414886055861039">"Pamja paraprake"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Ndryshoje te puna"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Ndryshoje te personale"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Kalo te profili i punës"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Kalo te profili personal"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Bllokuar nga administratori yt"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Qasja e të dhënave të punës nga një aplikacion personal nuk lejohet"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Qasja e të dhënave personale nga një aplikacion pune nuk lejohet"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Kontrollo lidhjen e internetit dhe provo përsëri"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Riprovo"</string> <string name="not_selected" msgid="2244008151669896758">"nuk është zgjedhur"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Media e zgjedhur po përgatitet"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> nga <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> gati"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Fotografitë e rezervuara tani janë të përfshira"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Mund të zgjedhësh fotografi nga llogaria e<xliff:g id="USER_ACCOUNT">%2$s</xliff:g> në <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Zgjidh aplikacionin"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Zgjidh llogarinë"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Ndrysho llogarinë"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Po merren të gjitha fotografitë e tua"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Të lejohet <xliff:g id="APP_NAME_0">^1</xliff:g> që ta modifikojë këtë skedar audio?}other{Të lejohet <xliff:g id="APP_NAME_1">^1</xliff:g> që të modifikojë <xliff:g id="COUNT">^2</xliff:g> skedarë audio?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Skedari audio po modifikohet…}other{<xliff:g id="COUNT">^1</xliff:g> skedarë audio po modifikohen…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Të lejohet <xliff:g id="APP_NAME_0">^1</xliff:g> që ta modifikojë këtë video?}other{Të lejohet <xliff:g id="APP_NAME_1">^1</xliff:g> që të modifikojë <xliff:g id="COUNT">^2</xliff:g> video?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Mbrojtja e sigurisë"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Sinjalizimet e transkodimit origjinal"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Progresi i transkodimit origjinal"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Disa fotografi nuk mund të ngarkohen"</string> + <string name="dialog_button_text" msgid="351366485240852280">"E kuptova"</string> </resources> diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 98f988e15..5540ae985 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Медији"</string> <string name="storage_description" msgid="4081716890357580107">"Локални меморијски простор"</string> <string name="app_label" msgid="9035307001052716210">"Меморијски простор за медије"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Медији"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Бирач медија"</string> <string name="artist_label" msgid="8105600993099120273">"Извођач"</string> <string name="unknown" msgid="2059049215682829375">"Непознато"</string> <string name="root_images" msgid="5861633549189045666">"Слике"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Приступајте медијима у клауду из"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Ништа"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Промена апликације за медије у клауду није успела."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Бирач медија"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Бирач медија"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Медији се синхронизују…"</string> <string name="add" msgid="2894574044585549298">"Додај"</string> <string name="deselect" msgid="4297825044827769490">"Опозови избор"</string> <string name="deselected" msgid="8488133193326208475">"Опозван је избор"</string> @@ -53,8 +56,8 @@ <string name="selected" msgid="9151797369975828124">"Изабрано"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{Изаберите највише <xliff:g id="COUNT_0">^1</xliff:g> ставку}one{Изаберите највише <xliff:g id="COUNT_1">^1</xliff:g> ставку}few{Изаберите највише <xliff:g id="COUNT_1">^1</xliff:g> ставке}other{Изаберите највише <xliff:g id="COUNT_1">^1</xliff:g> ставки}}"</string> <string name="recent" msgid="6694613584743207874">"Недавно"</string> - <string name="picker_photos_empty_message" msgid="5980619500554575558">"Нема слика нити видео снимака"</string> - <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Нема подржаних слика нити видео снимака"</string> + <string name="picker_photos_empty_message" msgid="5980619500554575558">"Нема слика нити видеа"</string> + <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Нема подржаних слика нити видеа"</string> <string name="picker_albums_empty_message" msgid="8341079772950966815">"Нема албума"</string> <string name="picker_view_selected" msgid="2266031384396143883">"Прикажи изабранo"</string> <string name="picker_photos" msgid="7415035516411087392">"Слике"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Проверите интернет везу и пробајте поново"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Пробај поново"</string> <string name="not_selected" msgid="2244008151669896758">"није изабрано"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Припремају се одабрани медијски фајлови"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Спремно:<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> од <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Сада су уврштене резервне копије слика"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Можете да изаберете слике са налога <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,34 +110,35 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Одабери апликацију"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Одабери налог"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Промени налог"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Преузимају се све слике"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> измени овај аудио фајл?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> аудио фајл?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> аудио фајла?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> аудио фајлова?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Мења се аудио фајл…}one{Мења се <xliff:g id="COUNT">^1</xliff:g> аудио фајл…}few{Мењају се <xliff:g id="COUNT">^1</xliff:g> аудио фајла…}other{Мења се <xliff:g id="COUNT">^1</xliff:g> аудио фајлова…}}"</string> - <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> измени овај видео?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> видео?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> видео снимка?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> видео снимака?}}"</string> - <string name="permission_progress_write_video" msgid="7014908418349819148">"{count,plural, =1{Мења се видео…}one{Мења се <xliff:g id="COUNT">^1</xliff:g> видео…}few{Мењају се <xliff:g id="COUNT">^1</xliff:g> видео снимка…}other{Мења се <xliff:g id="COUNT">^1</xliff:g> видео снимака…}}"</string> + <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> измени овај видео?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> видео?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> видео снимка?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> видеа?}}"</string> + <string name="permission_progress_write_video" msgid="7014908418349819148">"{count,plural, =1{Мења се видео…}one{Мења се <xliff:g id="COUNT">^1</xliff:g> видео…}few{Мењају се <xliff:g id="COUNT">^1</xliff:g> видео снимка…}other{Мења се <xliff:g id="COUNT">^1</xliff:g> видеа…}}"</string> <string name="permission_write_image" msgid="3518991791620523786">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> измени ову слику?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> слику?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> слике?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> слика?}}"</string> <string name="permission_progress_write_image" msgid="3623580315590025262">"{count,plural, =1{Мења се слика…}one{Мења се <xliff:g id="COUNT">^1</xliff:g> слика…}few{Мењају се <xliff:g id="COUNT">^1</xliff:g> слике…}other{Мења се <xliff:g id="COUNT">^1</xliff:g> слика…}}"</string> <string name="permission_write_generic" msgid="7431128739233656991">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> измени ову ставку?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> ставку?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> ставке?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> измени <xliff:g id="COUNT">^2</xliff:g> ставки?}}"</string> <string name="permission_progress_write_generic" msgid="2806560971318391443">"{count,plural, =1{Мења се ставка…}one{Мења се <xliff:g id="COUNT">^1</xliff:g> ставка…}few{Мењају се <xliff:g id="COUNT">^1</xliff:g> ставке…}other{Мења се <xliff:g id="COUNT">^1</xliff:g> ставки…}}"</string> <string name="permission_trash_audio" msgid="6554672354767742206">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести овај аудио фајл у отпад?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> аудио фајл у отпад?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> аудио фајла у отпад?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> аудио фајлова у отпад?}}"</string> <string name="permission_progress_trash_audio" msgid="3116279868733641329">"{count,plural, =1{Аудио фајл се премешта у отпад…}one{<xliff:g id="COUNT">^1</xliff:g> аудио фајл се премешта у отпад…}few{<xliff:g id="COUNT">^1</xliff:g> аудио фајла се премештају у отпад…}other{<xliff:g id="COUNT">^1</xliff:g> аудио фајлова се премешта у отпад…}}"</string> - <string name="permission_trash_video" msgid="7555850843259959642">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести овај видео у отпад?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео у отпад?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео снимка у отпад?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео снимака у отпад?}}"</string> - <string name="permission_progress_trash_video" msgid="4637821778329459681">"{count,plural, =1{Видео се премешта у отпад…}one{<xliff:g id="COUNT">^1</xliff:g> видео се премешта у отпад…}few{<xliff:g id="COUNT">^1</xliff:g> видео снимка се премештају у отпад…}other{<xliff:g id="COUNT">^1</xliff:g> видео снимака се премешта у отпад…}}"</string> + <string name="permission_trash_video" msgid="7555850843259959642">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести овај видео у отпад?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео у отпад?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео снимка у отпад?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видеа у отпад?}}"</string> + <string name="permission_progress_trash_video" msgid="4637821778329459681">"{count,plural, =1{Видео се премешта у отпад…}one{<xliff:g id="COUNT">^1</xliff:g> видео се премешта у отпад…}few{<xliff:g id="COUNT">^1</xliff:g> видео снимка се премештају у отпад…}other{<xliff:g id="COUNT">^1</xliff:g> видеа се премешта у отпад…}}"</string> <string name="permission_trash_image" msgid="3333128084684156675">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести ову слику у отпад?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> слику у отпад?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> слике у отпад?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> слика у отпад?}}"</string> <string name="permission_progress_trash_image" msgid="3063857679090024764">"{count,plural, =1{Слика се премешта у отпад…}one{<xliff:g id="COUNT">^1</xliff:g> слика се премешта у отпад…}few{<xliff:g id="COUNT">^1</xliff:g> слике се премештају у отпад…}other{<xliff:g id="COUNT">^1</xliff:g> слика се премешта у отпад…}}"</string> <string name="permission_trash_generic" msgid="5545420534785075362">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести ову ставку у отпад?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> ставку у отпад?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> ставке у отпад?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> ставки у отпад?}}"</string> <string name="permission_progress_trash_generic" msgid="7815124979717814057">"{count,plural, =1{Ставка се премешта у отпад…}one{<xliff:g id="COUNT">^1</xliff:g> ставка се премешта у отпад…}few{<xliff:g id="COUNT">^1</xliff:g> ставке се премештају у отпад…}other{<xliff:g id="COUNT">^1</xliff:g> ставки се премешта у отпад…}}"</string> <string name="permission_untrash_audio" msgid="8404597563284002472">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести овај аудио фајл из отпада?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> аудио фајл из отпада?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> аудио фајла из отпада?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> аудио фајлова из отпада?}}"</string> <string name="permission_progress_untrash_audio" msgid="2775372344946464508">"{count,plural, =1{Аудио фајл се премешта из отпада…}one{<xliff:g id="COUNT">^1</xliff:g> аудио фајл се премешта из отпада…}few{<xliff:g id="COUNT">^1</xliff:g> аудио фајла се премештају из отпада…}other{<xliff:g id="COUNT">^1</xliff:g> аудио фајлова се премешта из отпада…}}"</string> - <string name="permission_untrash_video" msgid="3178914827607608162">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести овај видео из отпада?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео из отпада?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео снимка из отпада?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео снимака из отпада?}}"</string> - <string name="permission_progress_untrash_video" msgid="5500929409733841567">"{count,plural, =1{Видео се премешта из отпада…}one{<xliff:g id="COUNT">^1</xliff:g> видео се премешта из отпада…}few{<xliff:g id="COUNT">^1</xliff:g> видео снимка се премештају из отпада…}other{<xliff:g id="COUNT">^1</xliff:g> видео снимака се премешта из отпада…}}"</string> + <string name="permission_untrash_video" msgid="3178914827607608162">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести овај видео из отпада?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео из отпада?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видео снимка из отпада?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> видеа из отпада?}}"</string> + <string name="permission_progress_untrash_video" msgid="5500929409733841567">"{count,plural, =1{Видео се премешта из отпада…}one{<xliff:g id="COUNT">^1</xliff:g> видео се премешта из отпада…}few{<xliff:g id="COUNT">^1</xliff:g> видео снимка се премештају из отпада…}other{<xliff:g id="COUNT">^1</xliff:g> видеа се премешта из отпада…}}"</string> <string name="permission_untrash_image" msgid="3397523279351032265">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести ову слику из отпада?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> слику из отпада?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> слике из отпада?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> слика из отпада?}}"</string> <string name="permission_progress_untrash_image" msgid="5295061520504846264">"{count,plural, =1{Слика се премешта из отпада…}one{<xliff:g id="COUNT">^1</xliff:g> слика се премешта из отпада…}few{<xliff:g id="COUNT">^1</xliff:g> слике се премештају из отпада…}other{<xliff:g id="COUNT">^1</xliff:g> слика се премешта из отпада…}}"</string> <string name="permission_untrash_generic" msgid="2118366929431671046">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> премести ову ставку из отпада?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> ставку из отпада?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> ставке из отпада?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> премести <xliff:g id="COUNT">^2</xliff:g> ставки из отпада?}}"</string> <string name="permission_progress_untrash_generic" msgid="1489511601966842579">"{count,plural, =1{Ставка се премешта из отпада…}one{<xliff:g id="COUNT">^1</xliff:g> ставка се премешта из отпада…}few{<xliff:g id="COUNT">^1</xliff:g> ставке се премештају из отпада…}other{<xliff:g id="COUNT">^1</xliff:g> ставки се премешта из отпада…}}"</string> <string name="permission_delete_audio" msgid="3326674742892796627">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> избрише овај аудио фајл?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> аудио фајл?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> аудио фајла?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> аудио фајлова?}}"</string> <string name="permission_progress_delete_audio" msgid="1734871539021696401">"{count,plural, =1{Брише се аудио фајл…}one{Брише се <xliff:g id="COUNT">^1</xliff:g> аудио фајл…}few{Бришу се <xliff:g id="COUNT">^1</xliff:g> аудио фајла…}other{Брише се <xliff:g id="COUNT">^1</xliff:g> аудио фајлова…}}"</string> - <string name="permission_delete_video" msgid="604024971828349279">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> избрише овај видео?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> видео?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> видео снимка?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> видео снимака?}}"</string> - <string name="permission_progress_delete_video" msgid="1846702435073793157">"{count,plural, =1{Брише се видео…}one{Брише се <xliff:g id="COUNT">^1</xliff:g> видео…}few{Бришу се <xliff:g id="COUNT">^1</xliff:g> видео снимка…}other{Брише се <xliff:g id="COUNT">^1</xliff:g> видео снимака…}}"</string> + <string name="permission_delete_video" msgid="604024971828349279">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> избрише овај видео?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> видео?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> видео снимка?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> видеа?}}"</string> + <string name="permission_progress_delete_video" msgid="1846702435073793157">"{count,plural, =1{Брише се видео…}one{Брише се <xliff:g id="COUNT">^1</xliff:g> видео…}few{Бришу се <xliff:g id="COUNT">^1</xliff:g> видео снимка…}other{Брише се <xliff:g id="COUNT">^1</xliff:g> видеа…}}"</string> <string name="permission_delete_image" msgid="3109056012794330510">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> избрише ову слику?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> слику?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> слике?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> слика?}}"</string> <string name="permission_progress_delete_image" msgid="8580517204901148906">"{count,plural, =1{Брише се слика…}one{Брише се <xliff:g id="COUNT">^1</xliff:g> слика…}few{Бришу се <xliff:g id="COUNT">^1</xliff:g> слике…}other{Брише се <xliff:g id="COUNT">^1</xliff:g> слика…}}"</string> <string name="permission_delete_generic" msgid="7891939881065520271">"{count,plural, =1{Желите ли да дозволите да <xliff:g id="APP_NAME_0">^1</xliff:g> избрише ову ставку?}one{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> ставку?}few{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> ставке?}other{Желите ли да дозволите да <xliff:g id="APP_NAME_1">^1</xliff:g> избрише <xliff:g id="COUNT">^2</xliff:g> ставки?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Сигурносна заштита"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Обавештења о основном транскодирању"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Ток основног транскодирања"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Учитавање неких слика није успело"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Важи"</string> </resources> diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 8f1ca526d..631e436f7 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Lokal lagring"</string> <string name="app_label" msgid="9035307001052716210">"Medialagring"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Medieväljaren"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Okänd"</string> <string name="root_images" msgid="5861633549189045666">"Bilder"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Få tillgång till media i molnet från"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Inga"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Det går inte att byta molnmedieapp just nu."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Medieväljaren"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Medieväljaren"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Synkroniserar media …"</string> <string name="add" msgid="2894574044585549298">"Lägg till"</string> <string name="deselect" msgid="4297825044827769490">"Avmarkera"</string> <string name="deselected" msgid="8488133193326208475">"Avmarkerad"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Kontrollera internetanslutningen och försök igen"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Försök igen"</string> <string name="not_selected" msgid="2244008151669896758">"inte valt"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Din valda media förbereds"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> av <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> är redo"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Säkerhetskopierade foton tas nu med"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Du kan välja foton från <xliff:g id="APP_NAME">%1$s</xliff:g>-kontot <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Välj app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Välj konto"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Byt konto"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Läser in alla dina foton"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Vill du tillåta att <xliff:g id="APP_NAME_0">^1</xliff:g> ändrar den här ljudfilen?}other{Vill du tillåta att <xliff:g id="APP_NAME_1">^1</xliff:g> ändrar <xliff:g id="COUNT">^2</xliff:g> ljudfiler?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Ljudfilen ändras …}other{<xliff:g id="COUNT">^1</xliff:g> ljudfiler ändras …}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Vill du tillåta att <xliff:g id="APP_NAME_0">^1</xliff:g> ändrar den här videon?}other{Vill du tillåta att <xliff:g id="APP_NAME_1">^1</xliff:g> ändrar <xliff:g id="COUNT">^2</xliff:g> videor?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Säkerhet"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Omkodningsvarningar för Native"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Omkodningsförlopp för Native"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Det gick inte att läsa in vissa foton"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 5cccb81cd..7e7f22aa5 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Maudhui"</string> <string name="storage_description" msgid="4081716890357580107">"Hifadhi ya ndani"</string> <string name="app_label" msgid="9035307001052716210">"Hifadhi ya Maudhui"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Maudhui"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Kiteua maudhui"</string> <string name="artist_label" msgid="8105600993099120273">"Msanii"</string> <string name="unknown" msgid="2059049215682829375">"Isiyojulikana"</string> <string name="root_images" msgid="5861633549189045666">"Picha"</string> @@ -39,13 +39,16 @@ <string name="allow" msgid="8885707816848569619">"Ruhusu"</string> <string name="deny" msgid="6040983710442068936">"Kataa"</string> <string name="picker_browse" msgid="5554477454636075934">"Vinjari…"</string> - <string name="picker_settings" msgid="6443463167344790260">"Programu ya maudhui ya Wingu"</string> - <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Programu ya maudhui ya Wingu"</string> - <string name="picker_settings_title" msgid="5647700706470673258">"Programu ya maudhui ya kwenye wingu"</string> + <string name="picker_settings" msgid="6443463167344790260">"Programu ya maudhui ya wingu"</string> + <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Programu ya maudhui ya wingu"</string> + <string name="picker_settings_title" msgid="5647700706470673258">"Programu ya maudhui ya wingu"</string> <string name="picker_settings_description" msgid="2916686824777214585">"Fikia maudhui kwenye wingu lako programu au tovuti inapokuomba uchague picha au video"</string> <string name="picker_settings_selection_message" msgid="245453573086488596">"Fikia maudhui ya kwenye wingu katika"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Hamna"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Imeshindwa kubadilisha programu ya maudhui ya wingu kwa wakati huu."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Kiteua maudhui"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Kiteua maudhui"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Inasawazisha maudhui…"</string> <string name="add" msgid="2894574044585549298">"Weka"</string> <string name="deselect" msgid="4297825044827769490">"Acha kuchagua"</string> <string name="deselected" msgid="8488133193326208475">"Umeacha kuchagua"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Picha"</string> <string name="picker_albums" msgid="4822511902115299142">"Albamu"</string> <string name="picker_preview" msgid="6257414886055861039">"Onyesho la kukagua"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Badili uweke wasifu wa kazini"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Badili uweke wasifu wa binafsi"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Badili utumie wasifu wa kazini"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Badili utumie wasifu wa binafsi"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Umezuiwa na msimamizi wako"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Huruhusiwi kufikia data ya kazini kwenye programu ya binafsi"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Huruhusiwi kufikia data binafsi kwenye programu ya kazini"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Angalia muunganisho wako wa intaneti na ujaribu tena"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Jaribu tena"</string> <string name="not_selected" msgid="2244008151669896758">"haijachaguliwa"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Inaandaa maudhui yako uliyochagua"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> kati ya <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ziko tayari"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Picha zilizohifadhiwa nakala zimejumuishwa sasa"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Unaweza kuchagua picha zilizotoka kwenye akaunti ya <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> katika programu ya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Chagua programu"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Chagua akaunti"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Badilisha akaunti"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Inapakia picha zako zote"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Ungependa kuruhusu <xliff:g id="APP_NAME_0">^1</xliff:g> ibadilishe faili hii ya sauti?}other{Ungependa kuruhusu <xliff:g id="APP_NAME_1">^1</xliff:g> ibadilishe faili <xliff:g id="COUNT">^2</xliff:g> za sauti?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Inarekebisha faili ya sauti…}other{Inarekebisha faili <xliff:g id="COUNT">^1</xliff:g> za sauti…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Ungependa kuruhusu <xliff:g id="APP_NAME_0">^1</xliff:g> ibadilishe video hii?}other{Ungependa kuruhusu <xliff:g id="APP_NAME_1">^1</xliff:g> ibadilishe video <xliff:g id="COUNT">^2</xliff:g>?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Ulinzi wa Usalama"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Arifa za Ubadilishaji Asilia wa Muundo wa Faili"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Maendeleo ya Ubadilishaji Asilia wa Muundo wa Faili"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Imeshindwa kupakia baadhi ya Picha"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Nimeelewa"</string> </resources> diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index 1241a5dd1..2e84a7834 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"மீடியா"</string> <string name="storage_description" msgid="4081716890357580107">"சாதனச் சேமிப்பகம்"</string> <string name="app_label" msgid="9035307001052716210">"மீடியா சேமிப்பிடம்"</string> - <string name="picker_app_label" msgid="4254039089502164761">"மீடியா"</string> + <string name="picker_app_label" msgid="1195424381053599122">"மீடியா தேர்வுக் கருவி"</string> <string name="artist_label" msgid="8105600993099120273">"கலைஞர்"</string> <string name="unknown" msgid="2059049215682829375">"அறியாதது"</string> <string name="root_images" msgid="5861633549189045666">"Images"</string> @@ -46,12 +46,15 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"கிளவுட் மீடியாவை இதிலிருந்து அணுகும்"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"எதுவுமில்லை"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"இப்போது கிளவுடு மீடியா ஆப்ஸை மாற்ற முடியாது"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"மீடியா தேர்வுக் கருவி"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"மீடியா தேர்வுக் கருவி"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"மீடியாவை ஒத்திசைக்கிறது…"</string> <string name="add" msgid="2894574044585549298">"சேர்"</string> <string name="deselect" msgid="4297825044827769490">"தேர்வுநீக்கு"</string> <string name="deselected" msgid="8488133193326208475">"தேர்வுநீக்கப்பட்டது"</string> <string name="select" msgid="2704765470563027689">"தேர்ந்தெடு"</string> <string name="selected" msgid="9151797369975828124">"தேர்ந்தெடுக்கப்பட்டது"</string> - <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> படத்தைத் தேர்ந்தெடுங்கள்}other{<xliff:g id="COUNT_1">^1</xliff:g> படங்களைத் தேர்ந்தெடுங்கள்}}"</string> + <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> படத்தைத் தேர்ந்தெடுங்கள்}other{<xliff:g id="COUNT_1">^1</xliff:g> படங்கள் வரை தேர்ந்தெடுங்கள்}}"</string> <string name="recent" msgid="6694613584743207874">"சமீபத்தியவை"</string> <string name="picker_photos_empty_message" msgid="5980619500554575558">"படங்களோ வீடியோக்களோ இல்லை"</string> <string name="picker_album_media_empty_message" msgid="7061850698189881671">"ஆதரிக்கப்படும் படங்களோ வீடியோக்களோ இல்லை"</string> @@ -93,9 +96,10 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"உங்கள் இணைய இணைப்பைச் சரிபார்த்துவிட்டு மீண்டும் முயலவும்"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"மீண்டும் முயல்க"</string> <string name="not_selected" msgid="2244008151669896758">"தேர்ந்தெடுக்கப்படவில்லை"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"நீங்கள் தேர்ந்தெடுத்த மீடியா தயாராகிறது"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> / <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> தயாராக உள்ளது"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"காப்புப் பிரதி எடுக்கப்பட்ட படங்கள் இப்போது சேர்க்கப்பட்டுள்ளன"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸிலிருந்தும் <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> கணக்கிலிருந்தும் படங்களைத் தேர்ந்தெடுக்கலாம்"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸில் <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> கணக்கிலிருந்தும் படங்களைத் தேர்ந்தெடுக்கலாம்"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g> கணக்கு புதுப்பிக்கப்பட்டது"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"<xliff:g id="USER_ACCOUNT">%1$s</xliff:g> கணக்கிலிருந்த படங்களும் இப்போது சேர்க்கப்பட்டுள்ளன"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"கிளவுட் மீடியா ஆப்ஸைத் தேர்வுசெய்தல்"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ஆப்ஸைத் தேர்வுசெய்க"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"கணக்கைத் தேர்வுசெய்க"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"கணக்கை மாற்று"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"உங்கள் படங்கள் அனைத்தையும் பெறுகிறது"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{இந்த ஆடியோ ஃபைலில் மாற்றங்களைச் செய்ய <xliff:g id="APP_NAME_0">^1</xliff:g> ஆப்ஸை அனுமதிக்கவா?}other{<xliff:g id="COUNT">^2</xliff:g> ஆடியோ ஃபைல்களில் மாற்றங்களைச் செய்ய <xliff:g id="APP_NAME_1">^1</xliff:g> ஆப்ஸை அனுமதிக்கவா?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ஆடியோ ஃபைலை மாற்றியமைக்கிறது…}other{<xliff:g id="COUNT">^1</xliff:g> ஆடியோ ஃபைல்களை மாற்றியமைக்கிறது…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{இந்த வீடியோவில் மாற்றங்களைச் செய்ய <xliff:g id="APP_NAME_0">^1</xliff:g> ஆப்ஸை அனுமதிக்கவா?}other{<xliff:g id="COUNT">^2</xliff:g> வீடியோக்களில் மாற்றங்களைச் செய்ய <xliff:g id="APP_NAME_1">^1</xliff:g> ஆப்ஸை அனுமதிக்கவா?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"பாதுகாப்பு வளையம்"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"நேட்டிவ் குறிமாற்ற விழிப்பூட்டல்கள்"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"நேட்டிவ் குறிமாற்றச் செயல்நிலை"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"சில படங்களைப் பதிவேற்ற முடியவில்லை"</string> + <string name="dialog_button_text" msgid="351366485240852280">"சரி"</string> </resources> diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index da65034f9..4da3c57a5 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"మీడియా"</string> <string name="storage_description" msgid="4081716890357580107">"స్థానిక స్టోరేజ్"</string> <string name="app_label" msgid="9035307001052716210">"మీడియా స్టోరేజ్"</string> - <string name="picker_app_label" msgid="4254039089502164761">"మీడియా"</string> + <string name="picker_app_label" msgid="1195424381053599122">"మీడియా సెలెక్టర్"</string> <string name="artist_label" msgid="8105600993099120273">"కళాకారుడు"</string> <string name="unknown" msgid="2059049215682829375">"తెలియదు"</string> <string name="root_images" msgid="5861633549189045666">"ఇమేజ్లు"</string> @@ -46,9 +46,12 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"దాని నుండి క్లౌడ్ మీడియాను యాక్సెస్ చేయండి"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ఏవీ లేవు"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"ఈ సమయంలో క్లౌడ్ మీడియా యాప్ మార్చడం సాధ్యపడలేదు."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"మీడియా సెలెక్టర్"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"మీడియా సెలెక్టర్"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"మీడియాను సింక్ చేస్తోంది…"</string> <string name="add" msgid="2894574044585549298">"జోడించండి"</string> <string name="deselect" msgid="4297825044827769490">"ఎంపికను తొలగించండి"</string> - <string name="deselected" msgid="8488133193326208475">"ఎంపికను తొలగించండి"</string> + <string name="deselected" msgid="8488133193326208475">"ఎంపిక తొలగించబడింది"</string> <string name="select" msgid="2704765470563027689">"ఎంచుకోండి"</string> <string name="selected" msgid="9151797369975828124">"ఎంచుకోబడింది"</string> <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{గరిష్ఠంగా <xliff:g id="COUNT_0">^1</xliff:g> ఐటెమ్ను ఎంచుకోండి}other{గరిష్ఠంగా <xliff:g id="COUNT_1">^1</xliff:g> ఐటెమ్లను ఎంచుకోండి}}"</string> @@ -60,7 +63,7 @@ <string name="picker_photos" msgid="7415035516411087392">"ఫోటోలు"</string> <string name="picker_albums" msgid="4822511902115299142">"ఆల్బమ్లు"</string> <string name="picker_preview" msgid="6257414886055861039">"ప్రివ్యూ"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"ఆఫీస్ ప్రొఫైల్కు మార్చండి"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"వర్క్ ప్రొఫైల్కు మార్చండి"</string> <string name="picker_personal_profile" msgid="639484258397758406">"వ్యక్తిగత ప్రొఫైల్కు మార్చండి"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"మీ అడ్మిన్ బ్లాక్ చేశారు"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"వ్యక్తిగత యాప్ నుండి వర్క్ డేటాను యాక్సెస్ చేయడం అనుమతించబడదు"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"మీ ఇంటర్నెట్ కనెక్షన్ను చెక్ చేసి, మళ్ళీ ట్రై చేయండి"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"మళ్లీ ట్రై చేయండి"</string> <string name="not_selected" msgid="2244008151669896758">"ఎంచుకోబడలేదు"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"మీరు ఎంచుకున్న మీడియాను సిద్ధం చేస్తోంది"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>లో <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> సిద్ధంగా ఉన్నాయి"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"బ్యాకప్ చేసిన ఫోటోలు ఇప్పుడు చేర్చబడ్డాయి"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"మీరు <xliff:g id="APP_NAME">%1$s</xliff:g> ఖాతా <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> నుండి ఫోటోలను ఎంచుకోవచ్చు"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"యాప్ను ఎంచుకోండి"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"ఖాతాను ఎంచుకోండి"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"ఖాతాను మార్చండి"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"మీ ఫోటోలన్నీ లోడ్ అవుతున్నాయి"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{ఈ ఆడియో ఫైల్ను ఎడిట్ చేయడానికి <xliff:g id="APP_NAME_0">^1</xliff:g>ను అనుమతించాలా?}other{<xliff:g id="COUNT">^2</xliff:g> ఆడియో ఫైళ్లను ఎడిట్ చేయడానికి <xliff:g id="APP_NAME_1">^1</xliff:g>ను అనుమతించాలా?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{ఆడియో ఫైల్ను సవరిస్తోంది…}other{<xliff:g id="COUNT">^1</xliff:g> ఆడియో ఫైళ్లను సవరిస్తోంది…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{ఈ వీడియోను ఎడిట్ చేయడానికి <xliff:g id="APP_NAME_0">^1</xliff:g>ను అనుమతించాలా?}other{<xliff:g id="COUNT">^2</xliff:g> వీడియోలను ఎడిట్ చేయడానికి <xliff:g id="APP_NAME_1">^1</xliff:g>ను అనుమతించాలా?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"భద్రత రక్షణ"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"స్థానిక ట్రాన్స్కోడ్ అలర్ట్లు"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"స్థానిక ట్రాన్స్కోడ్ ప్రోగ్రెస్"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"కొన్ని ఫోటోలను లోడ్ చేయడం సాధ్యపడదు"</string> + <string name="dialog_button_text" msgid="351366485240852280">"సరే"</string> </resources> diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 10ee54691..8a0ebf5ee 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"สื่อ"</string> <string name="storage_description" msgid="4081716890357580107">"พื้นที่เก็บข้อมูลในเครื่อง"</string> <string name="app_label" msgid="9035307001052716210">"พื้นที่เก็บข้อมูลสื่อ"</string> - <string name="picker_app_label" msgid="4254039089502164761">"สื่อ"</string> + <string name="picker_app_label" msgid="1195424381053599122">"เครื่องมือเลือกสื่อ"</string> <string name="artist_label" msgid="8105600993099120273">"ศิลปิน"</string> <string name="unknown" msgid="2059049215682829375">"ไม่ทราบ"</string> <string name="root_images" msgid="5861633549189045666">"รูปภาพ"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"เข้าถึงสื่อในระบบคลาวด์จาก"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"ไม่มี"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"เปลี่ยนแอปสื่อบนระบบคลาวด์ไม่ได้ในขณะนี้"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"เครื่องมือเลือกสื่อ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"เครื่องมือเลือกสื่อ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"กำลังซิงค์สื่อ…"</string> <string name="add" msgid="2894574044585549298">"เพิ่ม"</string> <string name="deselect" msgid="4297825044827769490">"ยกเลิกการเลือก"</string> <string name="deselected" msgid="8488133193326208475">"ยกเลิกการเลือก"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"ตรวจสอบการเชื่อมต่ออินเทอร์เน็ตและลองอีกครั้ง"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"ลองใหม่"</string> <string name="not_selected" msgid="2244008151669896758">"ไม่ได้เลือกไว้"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"กำลังเตรียมสื่อที่คุณเลือก"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"พร้อมแล้ว <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> จาก <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"รวมรูปภาพที่สำรองข้อมูลไว้แล้ว"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"คุณเลือกรูปภาพได้จากบัญชี <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> ของ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"เลือกแอป"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"เลือกบัญชี"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"เปลี่ยนบัญชี"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"กำลังโหลดรูปภาพทั้งหมด"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{อนุญาตให้ <xliff:g id="APP_NAME_0">^1</xliff:g> แก้ไขไฟล์เสียงนี้ไหม}other{อนุญาตให้ <xliff:g id="APP_NAME_1">^1</xliff:g> แก้ไขไฟล์เสียง <xliff:g id="COUNT">^2</xliff:g> ไฟล์ไหม}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{กำลังแก้ไขไฟล์เสียง…}other{กำลังแก้ไขไฟล์เสียง <xliff:g id="COUNT">^1</xliff:g> ไฟล์…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{อนุญาตให้ <xliff:g id="APP_NAME_0">^1</xliff:g> แก้ไขวิดีโอนี้ไหม}other{อนุญาตให้ <xliff:g id="APP_NAME_1">^1</xliff:g> แก้ไขวิดีโอ <xliff:g id="COUNT">^2</xliff:g> รายการไหม}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"การปกป้องเพื่อความปลอดภัย"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native Transcode Alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native Transcode Progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"โหลดรูปภาพบางรูปไม่ได้"</string> + <string name="dialog_button_text" msgid="351366485240852280">"รับทราบ"</string> </resources> diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 25f6d5302..fa6edae70 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Media"</string> <string name="storage_description" msgid="4081716890357580107">"Lokal na storage"</string> <string name="app_label" msgid="9035307001052716210">"Storage ng Media"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Tagapili ng media"</string> <string name="artist_label" msgid="8105600993099120273">"Artist"</string> <string name="unknown" msgid="2059049215682829375">"Hindi alam"</string> <string name="root_images" msgid="5861633549189045666">"Mga Larawan"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"I-access ang cloud media sa"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Wala"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Hindi mapalitan ang cloud media app sa ngayon."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Tagapili ng media"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Tagapili ng media"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Sini-sync ang media…"</string> <string name="add" msgid="2894574044585549298">"Magdagdag"</string> <string name="deselect" msgid="4297825044827769490">"I-deselect"</string> <string name="deselected" msgid="8488133193326208475">"Na-deselect"</string> @@ -57,7 +60,7 @@ <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Walang sinusuportahang larawan o video"</string> <string name="picker_albums_empty_message" msgid="8341079772950966815">"Walang album"</string> <string name="picker_view_selected" msgid="2266031384396143883">"Tingnan ang napili"</string> - <string name="picker_photos" msgid="7415035516411087392">"Photos"</string> + <string name="picker_photos" msgid="7415035516411087392">"Mga Larawan"</string> <string name="picker_albums" msgid="4822511902115299142">"Mga Album"</string> <string name="picker_preview" msgid="6257414886055861039">"Preview"</string> <string name="picker_work_profile" msgid="2083221066869141576">"Lumipat sa para sa trabaho"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Tingnan ang iyong koneksyon sa internet at subukan ulit"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Subukan ulit"</string> <string name="not_selected" msgid="2244008151669896758">"hindi pinili"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Inihahanda ang napili mong media"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Handa na ang <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> sa <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Kasama na ngayon ang mga na-back up na larawan"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Puwede kang pumili ng mga larawan mula sa <xliff:g id="APP_NAME">%1$s</xliff:g> account na <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Pumili ng app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Pumili ng account"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Magpalit ng account"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Kinukuha ang lahat ng iyong larawan"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Payagan ang <xliff:g id="APP_NAME_0">^1</xliff:g> na baguhin ang audio file na ito?}one{Payagan ang <xliff:g id="APP_NAME_1">^1</xliff:g> na baguhin ang <xliff:g id="COUNT">^2</xliff:g> audio file?}other{Payagan ang <xliff:g id="APP_NAME_1">^1</xliff:g> na baguhin ang <xliff:g id="COUNT">^2</xliff:g> na audio file?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Binabago ang audio file…}one{Nagbabago ng <xliff:g id="COUNT">^1</xliff:g> audio file…}other{Nagbabago ng <xliff:g id="COUNT">^1</xliff:g> na audio file…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Payagan ang <xliff:g id="APP_NAME_0">^1</xliff:g> na baguhin ang video na ito?}one{Payagan ang <xliff:g id="APP_NAME_1">^1</xliff:g> na baguhin ang <xliff:g id="COUNT">^2</xliff:g> video?}other{Payagan ang <xliff:g id="APP_NAME_1">^1</xliff:g> na baguhin ang <xliff:g id="COUNT">^2</xliff:g> na video?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Proteksyon sa kaligtasan"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Native Transcode Alerts"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Native Transcode Progress"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Hindi ma-load ang ilang Larawan"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 1a5101644..d7ff137b1 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Medya"</string> <string name="storage_description" msgid="4081716890357580107">"Yerel depolama"</string> <string name="app_label" msgid="9035307001052716210">"Medya Deposu"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Medya"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Medya seçme aracı"</string> <string name="artist_label" msgid="8105600993099120273">"Sanatçı"</string> <string name="unknown" msgid="2059049215682829375">"Bilinmiyor"</string> <string name="root_images" msgid="5861633549189045666">"Resimler"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Şuradaki bulut medyasına erişin"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Yok"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Bulut medya uygulaması şu anda değiştirilemiyor."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Medya seçme aracı"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Medya seçme aracı"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Medya senkronize ediliyor…"</string> <string name="add" msgid="2894574044585549298">"Ekle"</string> <string name="deselect" msgid="4297825044827769490">"Seçimi kaldır"</string> <string name="deselected" msgid="8488133193326208475">"Seçimi kaldırıldı"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"İnternet bağlantınızı kontrol edip tekrar deneyin"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Tekrar dene"</string> <string name="not_selected" msgid="2244008151669896758">"seçili değil"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Seçtiğiniz medyalar hazırlanıyor"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> adetten <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> adedi hazır"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Yedeklenen fotoğraflar artık dahil ediliyor"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasındaki <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> hesabından fotoğraf seçebilirsiniz"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Uygulama seç"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Hesap seç"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Hesabı değiştir"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Tüm fotoğraflarınız alınıyor"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> uygulamasının bu ses dosyasını değiştirmesine izin verilsin mi?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> uygulamasının <xliff:g id="COUNT">^2</xliff:g> ses dosyasını değiştirmesine izin verilsin mi?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Ses dosyası değiştiriliyor…}other{<xliff:g id="COUNT">^1</xliff:g> ses dosyası değiştiriliyor…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> uygulamasının bu videoyu değiştirmesine izin verilsin mi?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> uygulamasının <xliff:g id="COUNT">^2</xliff:g> videoyu değiştirmesine izin verilsin mi?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Güvenlik koruması"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Yerel Kod Dönüştürme Uyarıları"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Yerel Kod Dönüştürme İlerleme Durumu"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Bazı fotoğraflar yüklenemiyor"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Anladım"</string> </resources> diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 6706539b2..cce673b45 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Медіа-файли"</string> <string name="storage_description" msgid="4081716890357580107">"Локальна пам’ять"</string> <string name="app_label" msgid="9035307001052716210">"Сховище медіа-файлів"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Медіа"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Інструмент вибору медіаносія"</string> <string name="artist_label" msgid="8105600993099120273">"Виконавець"</string> <string name="unknown" msgid="2059049215682829375">"Невідомо"</string> <string name="root_images" msgid="5861633549189045666">"Зображення"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Постачальник медіаконтенту з хмари"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Немає"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Не вдалося змінити хмарний мультимедійний додаток."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Інструмент вибору медіаносія"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Інструмент вибору медіаносія"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Синхронізація медіаносіїв…"</string> <string name="add" msgid="2894574044585549298">"Додати"</string> <string name="deselect" msgid="4297825044827769490">"Не вибирати"</string> <string name="deselected" msgid="8488133193326208475">"Не вибрано"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Перевірте інтернет-з’єднання й повторіть спробу"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Повторити"</string> <string name="not_selected" msgid="2244008151669896758">"не вибрано"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Підготовка вибраних медіафайлів"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"Готово: <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> з <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g>"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Резервні копії фотографій додано"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Ви можете вибрати фотографії з облікового запису <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> у додатку <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Вибрати додаток"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Вибрати обліковий запис"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Змінити обліковий запис"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Завантажуються всі ваші фото"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Дозволити додатку <xliff:g id="APP_NAME_0">^1</xliff:g> змінити цей аудіофайл?}one{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> аудіофайл?}few{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> аудіофайли?}many{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> аудіофайлів?}other{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> аудіофайлу?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Змінення аудіофайлу…}one{Змінення <xliff:g id="COUNT">^1</xliff:g> аудіофайлу…}few{Змінення <xliff:g id="COUNT">^1</xliff:g> аудіофайлів…}many{Змінення <xliff:g id="COUNT">^1</xliff:g> аудіофайлів…}other{Змінення <xliff:g id="COUNT">^1</xliff:g> аудіофайлу…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Дозволити додатку <xliff:g id="APP_NAME_0">^1</xliff:g> змінити це відео?}one{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> відео?}few{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> відео?}many{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> відео?}other{Дозволити додатку <xliff:g id="APP_NAME_1">^1</xliff:g> змінити <xliff:g id="COUNT">^2</xliff:g> відео?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Захист"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Cповіщення про перекодування нативного коду"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Перебіг перекодування нативного коду"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Не вдається завантажити деякі фотографії"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 1206ef52a..fff4f4d4c 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"میڈیا"</string> <string name="storage_description" msgid="4081716890357580107">"مقامی اسٹوریج"</string> <string name="app_label" msgid="9035307001052716210">"میڈیا اسٹوریج"</string> - <string name="picker_app_label" msgid="4254039089502164761">"میڈیا"</string> + <string name="picker_app_label" msgid="1195424381053599122">"میڈیا منتخب کنندہ"</string> <string name="artist_label" msgid="8105600993099120273">"فنکار"</string> <string name="unknown" msgid="2059049215682829375">"نامعلوم"</string> <string name="root_images" msgid="5861633549189045666">"تصاوير"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"اس سے کلاؤڈ میڈیا تک رسائی حاصل کریں"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"کوئی نہیں"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"کلاؤڈ میڈیا ایپ کو اس وقت تبدیل نہیں کیا جا سکا۔"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"میڈیا منتخب کنندہ"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"میڈیا منتخب کنندہ"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"میڈیا کی مطابقت پذیری کی جا رہی ہے…"</string> <string name="add" msgid="2894574044585549298">"شامل کریں"</string> <string name="deselect" msgid="4297825044827769490">"غیر منتخب کریں"</string> <string name="deselected" msgid="8488133193326208475">"غیر منتخب کردہ"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"اپنا انٹرنیٹ کنکشن چیک کریں اور دوبارہ کوشش کریں"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"پھر کوشش کریں"</string> <string name="not_selected" msgid="2244008151669896758">"غیر منتخب کردہ"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"آپ کا منتخب کردہ میڈیا تیار کیا جا رہا ہے"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> میں سے <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> تیار ہیں"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"بیک اپ لی گئی تصاویر اب شامل ہیں"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"آپ <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> کے <xliff:g id="APP_NAME">%1$s</xliff:g> اکاؤنٹ سے تصاویر منتخب کر سکتے ہیں"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"ایپ منتخب کریں"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"اکاؤنٹ منتخب کریں"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"اکاؤنٹ تبدیل کریں"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"آپ کی تمام تصاویر حاصل کی جا رہی ہیں"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> کو اس آڈیو فائل میں ترمیم کرنے کی اجازت دیں؟}other{<xliff:g id="APP_NAME_1">^1</xliff:g> کو <xliff:g id="COUNT">^2</xliff:g> آڈیو فائلز میں ترمیم کرنے کی اجازت دیں؟}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{آڈیو فائل میں ترمیم کی جا رہی ہے…}other{<xliff:g id="COUNT">^1</xliff:g> آڈیو فائلز میں ترمیم کی جا رہی ہے…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> کو اس ویڈیو میں ترمیم کرنے کی اجازت دیں؟}other{<xliff:g id="APP_NAME_1">^1</xliff:g> کو <xliff:g id="COUNT">^2</xliff:g> ویڈیوز میں ترمیم کرنے کی اجازت دیں؟}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"سیفٹی پروٹیکشن"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"مقامی ٹرانسکوڈ کے الرٹس"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"مقامی ٹرانسکوڈ کی پیشرفت"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"کچھ تصاویر لوڈ نہیں کی جا سکتیں"</string> + <string name="dialog_button_text" msgid="351366485240852280">"سمجھ آ گئی"</string> </resources> diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 3f7f2d877..8287f989b 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Multimedia"</string> <string name="storage_description" msgid="4081716890357580107">"Mahalliy xotira"</string> <string name="app_label" msgid="9035307001052716210">"Multimedia xotirasi"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Media"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Rasm tanlash"</string> <string name="artist_label" msgid="8105600993099120273">"Ijrochi"</string> <string name="unknown" msgid="2059049215682829375">"Noaniq"</string> <string name="root_images" msgid="5861633549189045666">"Rasmlar"</string> @@ -46,12 +46,15 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Bulutli media kontentni ochish"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Hech qanday"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Hozirda bulutli media ilovasi oʻzgarmadi"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Rasm tanlash"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Rasm tanlash"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Media sinxronlanmoqda…"</string> <string name="add" msgid="2894574044585549298">"Kiritish"</string> <string name="deselect" msgid="4297825044827769490">"Tanlovni bekor qilish"</string> <string name="deselected" msgid="8488133193326208475">"Tanlovi yechilgan"</string> <string name="select" msgid="2704765470563027689">"Tanlash"</string> <string name="selected" msgid="9151797369975828124">"Tanlangan"</string> - <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> tagcha elementni tanlang}other{<xliff:g id="COUNT_1">^1</xliff:g> tagcha elementni tanlang}}"</string> + <string name="select_up_to" msgid="6994294169508439957">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> tagacha elementni tanlang}other{<xliff:g id="COUNT_1">^1</xliff:g> tagacha elementni tanlang}}"</string> <string name="recent" msgid="6694613584743207874">"Oxirgi"</string> <string name="picker_photos_empty_message" msgid="5980619500554575558">"Surat yoki video kiritilmagan"</string> <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Qabul qilinmaydigan rasm va videolar"</string> @@ -60,8 +63,8 @@ <string name="picker_photos" msgid="7415035516411087392">"Suratlar"</string> <string name="picker_albums" msgid="4822511902115299142">"Albomlar"</string> <string name="picker_preview" msgid="6257414886055861039">"Razm solish"</string> - <string name="picker_work_profile" msgid="2083221066869141576">"Ish profiliga oʻtish"</string> - <string name="picker_personal_profile" msgid="639484258397758406">"Shaxsiy profilga oʻtish"</string> + <string name="picker_work_profile" msgid="2083221066869141576">"Ish profiliga almashish"</string> + <string name="picker_personal_profile" msgid="639484258397758406">"Shaxsiy profilga almashish"</string> <string name="picker_profile_admin_title" msgid="4172022376418293777">"Administratoringiz tomonidan bloklangan"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Shaxsiy ilovadan ishga oid maʼlumotlarga kirish taqiqlangan"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Ishga oid ilovadan shaxsiy maʼlumotlarga kirish taqiqlangan"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Internet aloqasini tekshiring va qayta urining"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Qayta urinish"</string> <string name="not_selected" msgid="2244008151669896758">"tanlanmagan"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Tanlangan media tayyorlanmoqda"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> tayyor"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Zaxiralangan suratlar qoʻshildi"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"<xliff:g id="USER_ACCOUNT">%2$s</xliff:g> hisobidagi <xliff:g id="APP_NAME">%1$s</xliff:g> rasmlarini tanlashingiz mumkin"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Ilovani tanlash"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Hisobni tanlang"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Hisobni almashtirish"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Barcha rasmlaringizni yuklab oling"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ilovasiga bu audio faylni oʻzgartirishi uchun ruxsat berilsinmi?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> ilovasiga <xliff:g id="COUNT">^2</xliff:g> ta audio faylni oʻzgartirishi uchun ruxsat berilsinmi?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Audio fayl oʻzgartirilmoqda…}other{<xliff:g id="COUNT">^1</xliff:g> ta audio fayl oʻzgartirilmoqda…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{<xliff:g id="APP_NAME_0">^1</xliff:g> ilovasiga bu videoni oʻzgartirishi uchun ruxsat berilsinmi?}other{<xliff:g id="APP_NAME_1">^1</xliff:g> ilovasiga <xliff:g id="COUNT">^2</xliff:g> ta videoni oʻzgartirishi uchun ruxsat berilsinmi?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Xavfsizlik himoyasi"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Nativ transkodlash signallari"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Nativ transkodlash jarayoni"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Ayrim suratlar yuklanmadi"</string> + <string name="dialog_button_text" msgid="351366485240852280">"OK"</string> </resources> diff --git a/res/values-v31/styles.xml b/res/values-v31/styles.xml index 3dec1da72..85d3352e0 100644 --- a/res/values-v31/styles.xml +++ b/res/values-v31/styles.xml @@ -14,7 +14,8 @@ limitations under the License. --> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <style name="PickerMaterialTheme" parent="@style/Theme.Material3.DayNight.NoActionBar"> <item name="materialAlertDialogTheme">@style/ProfileDialogTheme</item> @@ -40,6 +41,8 @@ <item name="pickerBannerPrimaryTextColor">?android:attr/textColorSecondary</item> <item name="pickerBannerSecondaryTextColor">?android:attr/textColorPrimary</item> <item name="pickerBannerButtonTextColor">@android:color/system_accent1_600</item> + <item name="categoryDefaultThumbnailColor">@android:color/system_accent1_300</item> + <item name="categoryDefaultThumbnailCircleColor">?androidprv:attr/materialColorSurfaceContainer</item> </style> </resources> diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 471562e76..b2e077824 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Phương tiện"</string> <string name="storage_description" msgid="4081716890357580107">"Bộ nhớ cục bộ"</string> <string name="app_label" msgid="9035307001052716210">"Bộ nhớ phương tiện"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Nội dung nghe nhìn"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Công cụ chọn nội dung đa phương tiện"</string> <string name="artist_label" msgid="8105600993099120273">"Nghệ sĩ"</string> <string name="unknown" msgid="2059049215682829375">"Không xác định"</string> <string name="root_images" msgid="5861633549189045666">"Hình ảnh"</string> @@ -39,13 +39,16 @@ <string name="allow" msgid="8885707816848569619">"Cho phép"</string> <string name="deny" msgid="6040983710442068936">"Từ chối"</string> <string name="picker_browse" msgid="5554477454636075934">"Duyệt qua…"</string> - <string name="picker_settings" msgid="6443463167344790260">"Ứng dụng đa phương tiện trên đám mây"</string> - <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Ứng dụng đa phương tiện trên đám mây"</string> - <string name="picker_settings_title" msgid="5647700706470673258">"Ứng dụng nội dung phương tiện trên đám mây"</string> - <string name="picker_settings_description" msgid="2916686824777214585">"Truy cập vào nội dung nghe nhìn trên đám mây của bạn khi ứng dụng hoặc trang web yêu cầu bạn chọn ảnh hoặc video"</string> - <string name="picker_settings_selection_message" msgid="245453573086488596">"Truy cập nội dung phương tiện trên đám mây qua"</string> + <string name="picker_settings" msgid="6443463167344790260">"Ứng dụng nghe nhìn trên đám mây"</string> + <string name="picker_settings_system_settings_menu_title" msgid="3055084757610063581">"Ứng dụng nghe nhìn trên đám mây"</string> + <string name="picker_settings_title" msgid="5647700706470673258">"Ứng dụng nghe nhìn trên đám mây"</string> + <string name="picker_settings_description" msgid="2916686824777214585">"Truy cập vào nội dung nghe nhìn của bạn trên đám mây khi có ứng dụng hay trang web yêu cầu bạn chọn ảnh hoặc video"</string> + <string name="picker_settings_selection_message" msgid="245453573086488596">"Truy cập nội dung nghe nhìn trên đám mây qua"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Không có"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Hiện không thay đổi được ứng dụng đa phương tiện đám mây."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Công cụ chọn nội dung đa phương tiện"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Công cụ chọn nội dung đa phương tiện"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Đang đồng bộ hoá nội dung đa phương tiện…"</string> <string name="add" msgid="2894574044585549298">"Thêm"</string> <string name="deselect" msgid="4297825044827769490">"Bỏ chọn"</string> <string name="deselected" msgid="8488133193326208475">"Đã bỏ chọn"</string> @@ -55,14 +58,14 @@ <string name="recent" msgid="6694613584743207874">"Gần đây"</string> <string name="picker_photos_empty_message" msgid="5980619500554575558">"Không có ảnh hoặc video nào"</string> <string name="picker_album_media_empty_message" msgid="7061850698189881671">"Không có ảnh hoặc video nào được hỗ trợ"</string> - <string name="picker_albums_empty_message" msgid="8341079772950966815">"Không có đĩa nhạc nào"</string> + <string name="picker_albums_empty_message" msgid="8341079772950966815">"Không có album nào"</string> <string name="picker_view_selected" msgid="2266031384396143883">"Xem các mục được chọn"</string> <string name="picker_photos" msgid="7415035516411087392">"Ảnh"</string> <string name="picker_albums" msgid="4822511902115299142">"Album"</string> <string name="picker_preview" msgid="6257414886055861039">"Xem trước"</string> <string name="picker_work_profile" msgid="2083221066869141576">"Chuyển sang hồ sơ công việc"</string> <string name="picker_personal_profile" msgid="639484258397758406">"Chuyển sang hồ sơ cá nhân"</string> - <string name="picker_profile_admin_title" msgid="4172022376418293777">"Bị quản trị viên của bạn chặn"</string> + <string name="picker_profile_admin_title" msgid="4172022376418293777">"Quản trị viên của bạn đã chặn thao tác này"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"Bạn không được phép truy cập dữ liệu công việc từ một ứng dụng cá nhân"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"Bạn không được phép truy cập dữ liệu cá nhân từ một ứng dụng công việc"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"Ứng dụng công việc đã tạm dừng"</string> @@ -93,8 +96,9 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Hãy kiểm tra kết nối Internet rồi thử lại"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Thử lại"</string> <string name="not_selected" msgid="2244008151669896758">"chưa được chọn"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Đang chuẩn bị nội dung đa phương tiện mà bạn chọn"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g>/<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> mục đã sẵn sàng"</string> - <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Ảnh được sao lưu giờ đã xuất hiện"</string> + <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Ảnh được sao lưu giờ đã có mặt"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Bạn có thể chọn ảnh của <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> trên <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"Đã cập nhật tài khoản <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"Ảnh của <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> giờ sẽ xuất hiện tại đây"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Chọn ứng dụng"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Chọn tài khoản"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Thay đổi tài khoản"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Tải tất cả các ảnh"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Cho phép <xliff:g id="APP_NAME_0">^1</xliff:g> sửa đổi tệp âm thanh này?}other{Cho phép <xliff:g id="APP_NAME_1">^1</xliff:g> sửa đổi <xliff:g id="COUNT">^2</xliff:g> tệp âm thanh?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Đang sửa đổi tệp âm thanh…}other{Đang sửa đổi <xliff:g id="COUNT">^1</xliff:g> tệp âm thanh…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Cho phép <xliff:g id="APP_NAME_0">^1</xliff:g> sửa đổi video này?}other{Cho phép <xliff:g id="APP_NAME_1">^1</xliff:g> sửa đổi <xliff:g id="COUNT">^2</xliff:g> video?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Bảo vệ an toàn"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Cảnh báo chuyển mã gốc"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Tiến trình chuyển mã gốc"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Không tải được một số ảnh"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Tôi hiểu"</string> </resources> diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 57feea139..ca8149e97 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"媒体"</string> <string name="storage_description" msgid="4081716890357580107">"本地存储空间"</string> <string name="app_label" msgid="9035307001052716210">"媒体存储设备"</string> - <string name="picker_app_label" msgid="4254039089502164761">"媒体"</string> + <string name="picker_app_label" msgid="1195424381053599122">"媒体选择工具"</string> <string name="artist_label" msgid="8105600993099120273">"音乐人"</string> <string name="unknown" msgid="2059049215682829375">"未知"</string> <string name="root_images" msgid="5861633549189045666">"图片"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"从以下位置访问云端媒体:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"无"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"目前无法更改云端媒体应用。"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"媒体选择工具"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"媒体选择工具"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"正在同步媒体…"</string> <string name="add" msgid="2894574044585549298">"添加"</string> <string name="deselect" msgid="4297825044827769490">"取消选择"</string> <string name="deselected" msgid="8488133193326208475">"已取消选中"</string> @@ -93,19 +96,21 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"请检查互联网连接,然后重试"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"重试"</string> <string name="not_selected" msgid="2244008151669896758">"未选择"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"正在准备您选择的媒体"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> 个已准备就绪,共 <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> 个"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"备份照片现已添加完成"</string> - <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"您可以选择来自<xliff:g id="APP_NAME">%1$s</xliff:g>帐号 <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> 的照片"</string> - <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g>帐号已更新"</string> + <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"您可以选择来自<xliff:g id="APP_NAME">%1$s</xliff:g>账号 <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> 的照片"</string> + <string name="picker_banner_cloud_account_changed_title" msgid="4825058474378077327">"<xliff:g id="APP_NAME">%1$s</xliff:g>账号已更新"</string> <string name="picker_banner_cloud_account_changed_desc" msgid="3433218869899792497">"来自 <xliff:g id="USER_ACCOUNT">%1$s</xliff:g> 的照片已添加到此处"</string> <string name="picker_banner_cloud_choose_app_title" msgid="3165966147547974251">"选择云端媒体应用"</string> <string name="picker_banner_cloud_choose_app_desc" msgid="2359212653555524926">"如需将备份照片添加到此处,请在“设置”中选择一个云端媒体应用"</string> - <string name="picker_banner_cloud_choose_account_title" msgid="5010901185639577685">"选择<xliff:g id="APP_NAME">%1$s</xliff:g>帐号"</string> - <string name="picker_banner_cloud_choose_account_desc" msgid="8868134443673142712">"如需将来自<xliff:g id="APP_NAME">%1$s</xliff:g>的照片添加到此处,请在应用中选择一个帐号"</string> + <string name="picker_banner_cloud_choose_account_title" msgid="5010901185639577685">"选择<xliff:g id="APP_NAME">%1$s</xliff:g>账号"</string> + <string name="picker_banner_cloud_choose_account_desc" msgid="8868134443673142712">"如需将来自<xliff:g id="APP_NAME">%1$s</xliff:g>的照片添加到此处,请在应用中选择一个账号"</string> <string name="picker_banner_cloud_dismiss_button" msgid="2935903078288463882">"关闭"</string> <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"选择应用"</string> - <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"选择帐号"</string> - <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"更改帐号"</string> + <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"选择账号"</string> + <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"更改账号"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"正在获取您的所有照片"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{要允许<xliff:g id="APP_NAME_0">^1</xliff:g>修改这个音频文件吗?}other{要允许<xliff:g id="APP_NAME_1">^1</xliff:g>修改这 <xliff:g id="COUNT">^2</xliff:g> 个音频文件吗?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{正在修改音频文件…}other{正在修改 <xliff:g id="COUNT">^1</xliff:g> 个音频文件…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{要允许<xliff:g id="APP_NAME_0">^1</xliff:g>修改这个视频吗?}other{要允许<xliff:g id="APP_NAME_1">^1</xliff:g>修改这 <xliff:g id="COUNT">^2</xliff:g> 个视频吗?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"安全保护"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"原生转码警报"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"原生转码进度"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"部分照片无法加载"</string> + <string name="dialog_button_text" msgid="351366485240852280">"知道了"</string> </resources> diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 089d6fca1..34a87d5f8 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"媒體"</string> <string name="storage_description" msgid="4081716890357580107">"本機儲存空間"</string> <string name="app_label" msgid="9035307001052716210">"媒體儲存空間"</string> - <string name="picker_app_label" msgid="4254039089502164761">"媒體"</string> + <string name="picker_app_label" msgid="1195424381053599122">"媒體選擇器"</string> <string name="artist_label" msgid="8105600993099120273">"歌手"</string> <string name="unknown" msgid="2059049215682829375">"不明"</string> <string name="root_images" msgid="5861633549189045666">"相片"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"從以下位置存取雲端媒體:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"無"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"目前無法變更雲端媒體應用程式。"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"媒體選擇器"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"媒體選擇器"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"正在同步媒體…"</string> <string name="add" msgid="2894574044585549298">"新增"</string> <string name="deselect" msgid="4297825044827769490">"取消選取"</string> <string name="deselected" msgid="8488133193326208475">"已取消選取"</string> @@ -62,7 +65,7 @@ <string name="picker_preview" msgid="6257414886055861039">"預覽"</string> <string name="picker_work_profile" msgid="2083221066869141576">"切換至工作設定檔"</string> <string name="picker_personal_profile" msgid="639484258397758406">"切換至個人設定檔"</string> - <string name="picker_profile_admin_title" msgid="4172022376418293777">"管理員已禁止此操作"</string> + <string name="picker_profile_admin_title" msgid="4172022376418293777">"管理員禁止此操作"</string> <string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"個人應用程式不得存取工作資料"</string> <string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"工作應用程式不得存取個人資料"</string> <string name="picker_profile_work_paused_title" msgid="382212880704235925">"已暫停工作應用程式"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"請檢查你的互聯網連線,然後再試一次"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"重試"</string> <string name="not_selected" msgid="2244008151669896758">"未揀"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"正在準備你選取的媒體"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> 個項目已就緒,共 <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> 個"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"現在已納入備份相片"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"你可從「<xliff:g id="APP_NAME">%1$s</xliff:g>」帳戶 <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> 選取相片"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"選擇應用程式"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"選擇帳戶"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"變更帳戶"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"正在載入所有相片"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{允許 <xliff:g id="APP_NAME_0">^1</xliff:g> 修改此影片嗎?}other{允許 <xliff:g id="APP_NAME_1">^1</xliff:g> 修改 <xliff:g id="COUNT">^2</xliff:g> 部影片嗎?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{正在修改音訊檔案…}other{正在修改 <xliff:g id="COUNT">^1</xliff:g> 個音訊檔案…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{允許 <xliff:g id="APP_NAME_0">^1</xliff:g> 修改此影片嗎?}other{允許 <xliff:g id="APP_NAME_1">^1</xliff:g> 修改 <xliff:g id="COUNT">^2</xliff:g> 部影片嗎?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"安全保護"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"原生轉碼警示"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"原生轉碼進度"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"部分相片無法載入"</string> + <string name="dialog_button_text" msgid="351366485240852280">"知道了"</string> </resources> diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 0224634a4..05105779c 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"媒體"</string> <string name="storage_description" msgid="4081716890357580107">"本機儲存空間"</string> <string name="app_label" msgid="9035307001052716210">"媒體儲存空間"</string> - <string name="picker_app_label" msgid="4254039089502164761">"媒體"</string> + <string name="picker_app_label" msgid="1195424381053599122">"媒體選擇器"</string> <string name="artist_label" msgid="8105600993099120273">"演出者"</string> <string name="unknown" msgid="2059049215682829375">"不明"</string> <string name="root_images" msgid="5861633549189045666">"圖片"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"從以下位置存取雲端媒體:"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"無"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"目前無法變更雲端媒體應用程式。"</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"媒體選擇器"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"媒體選擇器"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"正在同步媒體…"</string> <string name="add" msgid="2894574044585549298">"新增"</string> <string name="deselect" msgid="4297825044827769490">"取消選取"</string> <string name="deselected" msgid="8488133193326208475">"已取消選取"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"請檢查網際網路連線,然後再試一次"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"重試"</string> <string name="not_selected" msgid="2244008151669896758">"未選取"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"正在準備所選媒體"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"已備妥 <xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> 個項目,共 <xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> 個項目"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"現在已納入備份相片"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"你可以從「<xliff:g id="APP_NAME">%1$s</xliff:g>」帳戶 <xliff:g id="USER_ACCOUNT">%2$s</xliff:g> 選取相片"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"選擇應用程式"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"選擇帳戶"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"變更帳戶"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"正在載入所有相片"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{允許「<xliff:g id="APP_NAME_0">^1</xliff:g>」修改這個音訊檔案嗎?}other{允許「<xliff:g id="APP_NAME_1">^1</xliff:g>」修改這 <xliff:g id="COUNT">^2</xliff:g> 個音訊檔案嗎?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{正在修改音訊檔案…}other{正在修改 <xliff:g id="COUNT">^1</xliff:g> 個音訊檔案…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{允許「<xliff:g id="APP_NAME_0">^1</xliff:g>」修改這部影片嗎?}other{允許「<xliff:g id="APP_NAME_1">^1</xliff:g>」修改這 <xliff:g id="COUNT">^2</xliff:g> 部影片嗎?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"安全防護"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"原生轉碼警示"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"原生轉碼進度"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"無法載入部分相片"</string> + <string name="dialog_button_text" msgid="351366485240852280">"我知道了"</string> </resources> diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index ed066d83f..979d2b3a0 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -19,7 +19,7 @@ <string name="uid_label" msgid="8421971615411294156">"Abezind"</string> <string name="storage_description" msgid="4081716890357580107">"Isitoreji sasendaweni"</string> <string name="app_label" msgid="9035307001052716210">"Isitoreji Semidiya"</string> - <string name="picker_app_label" msgid="4254039089502164761">"Imidiya"</string> + <string name="picker_app_label" msgid="1195424381053599122">"Isikhethi semidiya"</string> <string name="artist_label" msgid="8105600993099120273">"Umculi"</string> <string name="unknown" msgid="2059049215682829375">"Akwaziwa"</string> <string name="root_images" msgid="5861633549189045666">"Izithombe"</string> @@ -46,6 +46,9 @@ <string name="picker_settings_selection_message" msgid="245453573086488596">"Finyelela imidiya yacloud ukusuka"</string> <string name="picker_settings_no_provider" msgid="2582311853680058223">"Lutho"</string> <string name="picker_settings_toast_error" msgid="697274445512467469">"Ayikwazanga ukushintsha i-app yemidiya ye-cloud manje."</string> + <string name="picker_sync_notification_channel" msgid="1867105708912627993">"Isikhethi semidiya"</string> + <string name="picker_sync_notification_title" msgid="1122713382122055246">"Isikhethi semidiya"</string> + <string name="picker_sync_notification_text" msgid="8204423917712309382">"Ivumelanisa imidiya…"</string> <string name="add" msgid="2894574044585549298">"Engeza"</string> <string name="deselect" msgid="4297825044827769490">"Susa ukukhetha"</string> <string name="deselected" msgid="8488133193326208475">"Okususwe ekukhethweni"</string> @@ -93,6 +96,7 @@ <string name="picker_error_dialog_body" msgid="2515738446802971453">"Hlola ukuxhuma kwakho kwe-inthanethi uphinde uzame futhi"</string> <string name="picker_error_dialog_positive_action" msgid="749544129082109232">"Zama futhi"</string> <string name="not_selected" msgid="2244008151669896758">"akukhethiwe"</string> + <string name="preloading_dialog_title" msgid="4974348221848532887">"Ilungiselela imidiya yakho oyikhethile"</string> <string name="preloading_progress_message" msgid="4741327138031980582">"U-<xliff:g id="NUMBER_PRELOADED">%1$d</xliff:g> wokungu-<xliff:g id="NUMBER_TOTAL">%2$d</xliff:g> ulungile"</string> <string name="picker_banner_cloud_first_time_available_title" msgid="5912973744275711595">"Izithombe ezenziwe isipele sezifakiwe manje"</string> <string name="picker_banner_cloud_first_time_available_desc" msgid="5570916598348187607">"Ungakhetha izithombe ezivela ku-akhawunti ye-<xliff:g id="APP_NAME">%1$s</xliff:g> ethi <xliff:g id="USER_ACCOUNT">%2$s</xliff:g>"</string> @@ -106,6 +110,7 @@ <string name="picker_banner_cloud_choose_app_button" msgid="934085679890435479">"Khetha i-app"</string> <string name="picker_banner_cloud_choose_account_button" msgid="7979484877116991631">"Khetha i-akhawunti"</string> <string name="picker_banner_cloud_change_account_button" msgid="8361239765828471146">"Shintsha i-akhawunti"</string> + <string name="picker_loading_photos_message" msgid="6449180084857178949">"Ithola zonke izithombe zakho"</string> <string name="permission_write_audio" msgid="8819694245323580601">"{count,plural, =1{Vumela i-<xliff:g id="APP_NAME_0">^1</xliff:g> ukuguqula leli fayela lomsindo?}one{Vumela i-<xliff:g id="APP_NAME_1">^1</xliff:g> ukuguqula amafayela omsindo angu-<xliff:g id="COUNT">^2</xliff:g>?}other{Vumela i-<xliff:g id="APP_NAME_1">^1</xliff:g> ukuguqula amafayela omsindo angu-<xliff:g id="COUNT">^2</xliff:g>?}}"</string> <string name="permission_progress_write_audio" msgid="6029375427984180097">"{count,plural, =1{Ilungisa ifayela lomsindo…}one{Ilungisa amafayela womsindo angu-<xliff:g id="COUNT">^1</xliff:g>…}other{Ilungisa amafayela womsindo angu-<xliff:g id="COUNT">^1</xliff:g>…}}"</string> <string name="permission_write_video" msgid="103902551603700525">"{count,plural, =1{Vumela i-<xliff:g id="APP_NAME_0">^1</xliff:g> ukuguqula le vidiyo?}one{Vumela i-<xliff:g id="APP_NAME_1">^1</xliff:g> ukuguqula amavidiyo angu-<xliff:g id="COUNT">^2</xliff:g>?}other{Vumela i-<xliff:g id="APP_NAME_1">^1</xliff:g> ukuguqula amavidiyo angu-<xliff:g id="COUNT">^2</xliff:g>?}}"</string> @@ -149,4 +154,8 @@ <string name="safety_protection_icon_label" msgid="6714354052747723623">"Ukuvikeleka kokuphepha"</string> <string name="transcode_alert_channel" msgid="997332371757680478">"Izexwayiso Zokudlulisela Ikhodi Yomdabu"</string> <string name="transcode_progress_channel" msgid="6905136787933058387">"Inqubekela-phambili Yokudlulisela Ikhodi Yomdabu"</string> + <!-- no translation found for dialog_error_message (5120432204743681606) --> + <skip /> + <string name="dialog_error_title" msgid="636349284077820636">"Ayikwazi ukulayisha ezinye Izithombe"</string> + <string name="dialog_button_text" msgid="351366485240852280">"Ngiyezwa"</string> </resources> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 6f53ce1bf..c932084b8 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -78,4 +78,10 @@ <!-- Photo Picker Banner button text color. --> <attr name="pickerBannerButtonTextColor" format="reference|color" /> + <!-- Default thumbnail icon color for merged albums --> + <attr name="categoryDefaultThumbnailColor" format="reference|color"/> + + <!-- Default thumbnail ellipse color for merged albums --> + <attr name="categoryDefaultThumbnailCircleColor" format="reference|color" /> + </resources> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index de1540dfa..90013b745 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -19,6 +19,7 @@ <dimen name="permission_thumb_size">64dp</dimen> <dimen name="permission_thumb_margin">6dp</dimen> <dimen name="dialog_space">20dp</dimen> + <dimen name="button_touch_size">48dp</dimen> <!-- PhotoPicker --> <dimen name="picker_top_corner_radius">28dp</dimen> diff --git a/res/values/strings.xml b/res/values/strings.xml index b494869b5..53f3fa82c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -26,7 +26,7 @@ <string name="app_label">Media Storage</string> <!-- Label to show to user for this package and for Photo picker. --> - <string name="picker_app_label">Media</string> + <string name="picker_app_label">Media picker</string> <!-- Description line for music artists in the search/suggestion results --> <string name="artist_label">Artist</string> @@ -107,6 +107,15 @@ <!-- Error message displayed to the user when the user is not able to change cloud media app preference in Picker Settings. [CHAR LIMIT=50] --> <string name="picker_settings_toast_error">Could not change cloud media app at this time.</string> + <!-- PhotoPicker notification channel for sync updates [CHAR LIMIT=40] --> + <string name="picker_sync_notification_channel">Media picker</string> + + <!-- PhotoPicker sync notification title [CHAR LIMIT=40] --> + <string name="picker_sync_notification_title">Media picker</string> + + <!-- PhotoPicker sync notification text [CHAR LIMIT=60] --> + <string name="picker_sync_notification_text">Syncing media…</string> + <!-- Add button for PhotoPicker. [CHAR LIMIT=30] --> <string name="add">Add</string> @@ -138,7 +147,7 @@ <!-- The message for empty message on Albums tab in PhotoPicker when the item count is zero. [CHAR LIMIT=NONE] --> <string name="picker_albums_empty_message">No albums</string> - <!-- PhotoPicker view selected action text. [CHAR LIMIT=80] --> + <!-- PhotoPicker view selected action text. [CHAR LIMIT=17] --> <string name="picker_view_selected">View selected</string> <!-- The text of the photos tab for PhotoPicker. [CHAR LIMIT=30] --> @@ -244,6 +253,8 @@ <!-- Default not selected text used by accessibility for an element that can be unselected. [CHAR LIMIT=NONE] --> <string name="not_selected">not selected</string> + <!-- Title of the preloading progress dialog --> + <string name="preloading_dialog_title">"Preparing your selected media"</string> <!-- A message for the Progress Dialog shown while preloading selected items before "closing" Photo Picker. [CHAR LIMIT=NONE] --> <string name="preloading_progress_message"><xliff:g id="number_preloaded">%1$d</xliff:g> of <xliff:g id="number_total">%2$d</xliff:g> ready</string> @@ -499,4 +510,13 @@ <!-- Transcode progress channel name. --> <string name="transcode_progress_channel">Native Transcode Progress</string> + + <!-- Dialog error message--> + <string name="dialog_error_message">Try again later. Your photos will be available once the issue is resolved.</string> + + <!-- Dialog error title--> + <string name="dialog_error_title">Can\'t load some Photos</string> + + <!-- Error dialog OK button text--> + <string name="dialog_button_text">Got it</string> </resources> diff --git a/res/values/styles.xml b/res/values/styles.xml index d499105f7..179edf839 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -14,7 +14,8 @@ limitations under the License. --> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <style name="PickerDialogTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"> @@ -89,6 +90,7 @@ <style name="PickerDefaultTheme" parent="@android:style/Theme.DeviceDefault.DayNight"> <!-- System | Widget section --> + <item name="actionOverflowButtonStyle">@style/OverflowButtonStyle</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:navigationBarColor">@color/picker_background_color</item> <item name="android:statusBarColor">@android:color/transparent</item> @@ -127,6 +129,8 @@ <item name="pickerBannerPrimaryTextColor">?android:attr/textColorSecondary</item> <item name="pickerBannerSecondaryTextColor">?android:attr/textColorPrimary</item> <item name="pickerBannerButtonTextColor">?android:attr/colorAccent</item> + <item name="categoryDefaultThumbnailColor">?android:attr/colorAccent</item> + <item name="categoryDefaultThumbnailCircleColor">?androidprv:attr/materialColorSurfaceContainer</item> </style> <style name="PickerBannerButtonTheme" @@ -138,4 +142,18 @@ <item name="android:textColor">?attr/pickerBannerButtonTextColor</item> </style> + <style name="OverflowButtonStyle" parent="Widget.AppCompat.ActionButton.Overflow"> + <item name="android:minWidth">@dimen/button_touch_size</item> + </style> + + <style name="SelectedMediaPreloaderDialogTheme" + parent="@style/ThemeOverlay.MaterialComponents.MaterialAlertDialog.Centered"> + <item name="android:textColor">?attr/colorOnSurfaceVariant</item> + <item name="materialAlertDialogTitleTextStyle">@style/AlertDialogTitleStyle</item> + </style> + + <style name="AlertDialogTitleStyle" + parent="@style/MaterialAlertDialog.MaterialComponents.Title.Text.CenterStacked"> + <item name="android:textColor">?attr/colorOnSurface</item> + </style> </resources> diff --git a/src/com/android/providers/media/ConfigStore.java b/src/com/android/providers/media/ConfigStore.java index cceb73424..83955280b 100644 --- a/src/com/android/providers/media/ConfigStore.java +++ b/src/com/android/providers/media/ConfigStore.java @@ -67,6 +67,7 @@ public interface ConfigStore { boolean DEFAULT_CLOUD_MEDIA_IN_PHOTO_PICKER_ENABLED = false; boolean DEFAULT_ENFORCE_CLOUD_PROVIDER_ALLOWLIST = true; + boolean DEFAULT_PICKER_CHOICE_MANAGED_SELECTION_ENABLED = false; /** * @return if the Cloud-Media-in-Photo-Picker enabled (e.g. platform will recognize and @@ -77,6 +78,14 @@ public interface ConfigStore { } /** + * @return if the Picker-Choice_Managed_selection is enabled. + */ + default boolean isPickerChoiceManagedSelectionEnabled() { + return DEFAULT_PICKER_CHOICE_MANAGED_SELECTION_ENABLED; + } + + + /** * @return package name of the pre-configured "system default" * {@link android.provider.CloudMediaProvider}. * @see #isCloudMediaInPhotoPickerEnabled() @@ -242,7 +251,7 @@ public interface ConfigStore { private static final String KEY_USER_SELECT_FOR_APP = "user_select_for_app"; @VisibleForTesting - public static final String KEY_STABILIZE_VOLUME_INTERNAL = "stablize_volume_internal"; + public static final String KEY_STABILIZE_VOLUME_INTERNAL = "stabilize_volume_internal"; @VisibleForTesting public static final String KEY_STABILIZE_VOLUME_EXTERNAL = "stabilize_volume_external"; @@ -264,6 +273,8 @@ public interface ConfigStore { "picker_pick_images_respect_preload_selected_arg"; private static final String KEY_CLOUD_MEDIA_FEATURE_ENABLED = "cloud_media_feature_enabled"; + private static final String KEY_PICKER_CHOICE_MANAGED_SELECTION_ENABLED = + "picker_choice_managed_selection_enabled"; private static final String KEY_CLOUD_MEDIA_PROVIDER_ALLOWLIST = "allowed_cloud_providers"; private static final String KEY_CLOUD_MEDIA_ENFORCE_PROVIDER_ALLOWLIST = "cloud_media_enforce_provider_allowlist"; @@ -279,8 +290,27 @@ public interface ConfigStore { @Override public boolean isCloudMediaInPhotoPickerEnabled() { - return getBooleanDeviceConfig(NAMESPACE_MEDIAPROVIDER, KEY_CLOUD_MEDIA_FEATURE_ENABLED, - DEFAULT_CLOUD_MEDIA_IN_PHOTO_PICKER_ENABLED); + Boolean isEnabled = + getBooleanDeviceConfig( + NAMESPACE_MEDIAPROVIDER, + KEY_CLOUD_MEDIA_FEATURE_ENABLED, + DEFAULT_CLOUD_MEDIA_IN_PHOTO_PICKER_ENABLED); + + List<String> allowList = + getStringArrayDeviceConfig( + NAMESPACE_MEDIAPROVIDER, KEY_CLOUD_MEDIA_PROVIDER_ALLOWLIST); + + // Only consider the feature enabled when the enabled flag is on AND when the allowlist + // of permitted cloud media providers is not empty. + return isEnabled && !allowList.isEmpty(); + } + + @Override + public boolean isPickerChoiceManagedSelectionEnabled() { + return getBooleanDeviceConfig( + NAMESPACE_MEDIAPROVIDER, + KEY_PICKER_CHOICE_MANAGED_SELECTION_ENABLED, + DEFAULT_PICKER_CHOICE_MANAGED_SELECTION_ENABLED); } @Nullable diff --git a/src/com/android/providers/media/DatabaseBackupAndRecovery.java b/src/com/android/providers/media/DatabaseBackupAndRecovery.java index 69df6a663..39039759d 100644 --- a/src/com/android/providers/media/DatabaseBackupAndRecovery.java +++ b/src/com/android/providers/media/DatabaseBackupAndRecovery.java @@ -132,11 +132,6 @@ public class DatabaseBackupAndRecovery { }; /** - * Wait time of 5 seconds in millis. - */ - private static final long WAIT_TIME_5_SECONDS_IN_MILLIS = 5000; - - /** * Wait time of 10 seconds in millis. */ private static final long WAIT_TIME_10_SECONDS_IN_MILLIS = 10000; @@ -234,8 +229,7 @@ public class DatabaseBackupAndRecovery { if (!new File(RECOVERY_DIRECTORY_PATH).exists()) { new File(RECOVERY_DIRECTORY_PATH).mkdirs(); } - FuseDaemon fuseDaemon = getFuseDaemonForFileWithWait(volumePath, - WAIT_TIME_5_SECONDS_IN_MILLIS); + FuseDaemon fuseDaemon = getFuseDaemonForFileWithWait(volumePath); Log.d(TAG, "Received db backup Fuse Daemon for: " + volumeName); fuseDaemon.setupVolumeDbBackup(); mIsBackupSetupComplete.set(true); @@ -261,9 +255,14 @@ public class DatabaseBackupAndRecovery { return Optional.empty(); } - final String fuseDaemonFilePath = getFuseDaemonFilePath(filePath); + final String fuseDaemonFilePath = getFilePathForFuseRequests(filePath); try { final String data = getFuseDaemonForPath(fuseDaemonFilePath).readBackedUpData(filePath); + if (data == null || data.isEmpty()) { + Log.w(TAG, "No backup found for path: " + filePath); + return Optional.empty(); + } + return Optional.of(BackupIdRow.deserialize(data)); } catch (Exception e) { Log.e(TAG, "Failure in getting backed up data for filePath: " + filePath, e); @@ -325,8 +324,7 @@ public class DatabaseBackupAndRecovery { FuseDaemon fuseDaemon; try { - fuseDaemon = getFuseDaemonForFileWithWait(new File(EXTERNAL_PRIMARY_ROOT_PATH), - WAIT_TIME_5_SECONDS_IN_MILLIS); + fuseDaemon = getFuseDaemonForFileWithWait(new File(EXTERNAL_PRIMARY_ROOT_PATH)); } catch (FileNotFoundException e) { Log.e(TAG, "Fuse Daemon not found for primary external storage, skipping backing up of " @@ -343,7 +341,7 @@ public class DatabaseBackupAndRecovery { if (lastBackedGenerationNumber > 0) { Log.i(TAG, "Last backed up generation number is " + lastBackedGenerationNumber); } - final String generationClause = MediaStore.Files.FileColumns.GENERATION_MODIFIED + " > " + final String generationClause = MediaStore.Files.FileColumns.GENERATION_MODIFIED + " >= " + lastBackedGenerationNumber; final String volumeClause = MediaStore.Files.FileColumns.VOLUME_NAME + " = '" + MediaStore.VOLUME_EXTERNAL_PRIMARY + "'"; @@ -457,10 +455,9 @@ public class DatabaseBackupAndRecovery { return; } - // For all internal file paths, redirect to external primary fuse daemon. - final String fuseDaemonFilePath = getFuseDaemonFilePath(insertedRow.getPath()); try { - FuseDaemon fuseDaemon = getFuseDaemonForPath(fuseDaemonFilePath); + FuseDaemon fuseDaemon = getFuseDaemonForPath( + getFilePathForFuseRequests(insertedRow.getPath())); final BackupIdRow value = createBackupIdRow(fuseDaemon, insertedRow); fuseDaemon.backupVolumeDbData(insertedRow.getPath(), BackupIdRow.serialize(value)); } catch (Exception e) { @@ -468,8 +465,21 @@ public class DatabaseBackupAndRecovery { } } - private String getFuseDaemonFilePath(String filePath) { - return filePath.startsWith("/storage") ? filePath : EXTERNAL_PRIMARY_ROOT_PATH; + /** + * Creates a fuse daemon file path for a given path. + */ + protected static String getFilePathForFuseRequests(String filePath) { + // For internal volume paths + if (!filePath.startsWith("/storage")) { + return EXTERNAL_PRIMARY_ROOT_PATH; + } + + // For primary external and cloned app paths. + if (filePath.equalsIgnoreCase("/storage") || filePath.startsWith("/storage/emulated")) { + return EXTERNAL_PRIMARY_ROOT_PATH; + } + + return filePath; } private BackupIdRow createBackupIdRow(FuseDaemon fuseDaemon, FileRow insertedRow) @@ -599,10 +609,9 @@ public class DatabaseBackupAndRecovery { return; } - // For all internal file paths, redirect to external primary fuse daemon. - String fuseDaemonFilePath = getFuseDaemonFilePath(deletedFilePath); try { - getFuseDaemonForPath(fuseDaemonFilePath).deleteDbBackup(deletedFilePath); + getFuseDaemonForPath(getFilePathForFuseRequests(deletedFilePath)).deleteDbBackup( + deletedFilePath); } catch (IOException e) { Log.w(TAG, "Failure in deleting backup data for key: " + deletedFilePath, e); } @@ -637,10 +646,9 @@ public class DatabaseBackupAndRecovery { } final String updatedFilePath = updatedRow.getPath(); - // For all internal file paths, redirect to external primary fuse daemon. - final String fuseDaemonFilePath = getFuseDaemonFilePath(updatedFilePath); try { - getFuseDaemonForPath(fuseDaemonFilePath).backupVolumeDbData(updatedFilePath, + getFuseDaemonForPath(getFilePathForFuseRequests(updatedFilePath)).backupVolumeDbData( + updatedFilePath, BackupIdRow.serialize(BackupIdRow.newBuilder(updatedRow.getId()).setIsDirty( true).build())); } catch (IOException e) { @@ -807,7 +815,7 @@ public class DatabaseBackupAndRecovery { // Wait for external primary to be attached as we use same thread for internal volume. // Maximum wait for 10s try { - getFuseDaemonForFileWithWait(new File(fuseFilePath), WAIT_TIME_10_SECONDS_IN_MILLIS); + getFuseDaemonForFileWithWait(new File(fuseFilePath)); } catch (FileNotFoundException e) { Log.e(TAG, "Could not recover data as fuse daemon could not serve requests.", e); return; @@ -828,7 +836,7 @@ public class DatabaseBackupAndRecovery { while (true) { backedUpFilePaths = readBackedUpFilePaths(volumeName, lastReadValue, LEVEL_DB_READ_LIMIT); - if (backedUpFilePaths.length <= 0) { + if (backedUpFilePaths.length == 0) { break; } @@ -868,10 +876,11 @@ public class DatabaseBackupAndRecovery { return new File(RECOVERY_DIRECTORY_PATH).exists(); } - protected FuseDaemon getFuseDaemonForFileWithWait(File fuseFilePath, long waitTime) + protected FuseDaemon getFuseDaemonForFileWithWait(File fuseFilePath) throws FileNotFoundException { pollForExternalStorageMountedState(); - return MediaProvider.getFuseDaemonForFileWithWait(fuseFilePath, mVolumeCache, waitTime); + return MediaProvider.getFuseDaemonForFileWithWait(fuseFilePath, mVolumeCache, + WAIT_TIME_10_SECONDS_IN_MILLIS); } private int getVolumeNameForStatsLog(String volumeName) { @@ -912,7 +921,7 @@ public class DatabaseBackupAndRecovery { FuseDaemon fuseDaemon; try { - fuseDaemon = getFuseDaemonForPath(EXTERNAL_PRIMARY_ROOT_PATH); + fuseDaemon = getFuseDaemonForPath(getFilePathForFuseRequests(oldRow.getPath())); } catch (FileNotFoundException e) { Log.e(TAG, "Fuse Daemon not found for primary external storage, skipping update of " @@ -927,7 +936,6 @@ public class DatabaseBackupAndRecovery { null, null)) { if (c.moveToFirst()) { backupDataValues(fuseDaemon, c); - Log.v(TAG, "Updated backed up row in leveldb"); String newPath = c.getString(1); if (oldRow.getPath() != null && !oldRow.getPath().equalsIgnoreCase(newPath)) { // If file path has changed, update leveldb backup to delete old path. @@ -967,11 +975,14 @@ public class DatabaseBackupAndRecovery { */ protected void removeRecoveryDataExceptValidUsers(List<String> validUsers) { List<String> xattrList = listXattr(DATA_MEDIA_XATTR_DIRECTORY_PATH); + Log.i(TAG, "Xattr list is " + xattrList); if (xattrList.isEmpty()) { return; } + Log.i(TAG, "Valid users list is " + validUsers); List<String> invalidUsers = getInvalidUsersList(xattrList, validUsers); + Log.i(TAG, "Invalid users list is " + invalidUsers); for (String userIdToBeRemoved : invalidUsers) { removeRecoveryDataForUserId(Integer.parseInt(userIdToBeRemoved)); } diff --git a/src/com/android/providers/media/MediaGrants.java b/src/com/android/providers/media/MediaGrants.java index b08bb63d8..bdeeb7485 100644 --- a/src/com/android/providers/media/MediaGrants.java +++ b/src/com/android/providers/media/MediaGrants.java @@ -16,10 +16,14 @@ package com.android.providers.media; +import static android.provider.MediaStore.MediaColumns.DATA; + import static com.android.providers.media.LocalUriMatcher.PICKER_ID; import android.content.ContentUris; import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.provider.MediaStore; @@ -29,7 +33,9 @@ import android.util.Log; import androidx.annotation.NonNull; import com.android.providers.media.photopicker.PickerSyncController; +import com.android.providers.media.util.FileUtils; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -47,6 +53,9 @@ class MediaGrants { public static final String OWNER_PACKAGE_NAME_COLUMN = MediaStore.MediaColumns.OWNER_PACKAGE_NAME; + private static final String MEDIA_GRANTS_AND_FILES_JOIN_TABLE_NAME = "media_grants LEFT JOIN " + + "files ON media_grants.file_id = files._id"; + private SQLiteQueryBuilder mQueryBuilder = new SQLiteQueryBuilder(); private DatabaseHelper mExternalDatabase; private LocalUriMatcher mUriMatcher; @@ -87,7 +96,15 @@ class MediaGrants { values.put(FILE_ID_COLUMN, id); values.put(PACKAGE_USER_ID_COLUMN, packageUserId); - mQueryBuilder.insert(db, values); + try { + mQueryBuilder.insert(db, values); + } catch (SQLiteConstraintException exception) { + // no-op + // this may happen due to the presence of a foreign key between the + // media_grants and files table. An SQLiteConstraintException + // exception my occur if: while inserting the grant for a file, the + // file itself is deleted. In this situation no operation is required. + } } Log.d( @@ -101,6 +118,41 @@ class MediaGrants { } /** + * Returns the file uris of items for which the passed package has READ_GRANTS. + * + * @param packageName the package name that has access. + * @param packageUserId the user_id of the package + */ + List<Uri> getMediaGrantsForPackage(String packageName, int packageUserId) + throws IllegalArgumentException { + Objects.requireNonNull(packageName); + return mExternalDatabase.runWithoutTransaction((db) -> { + final List<Uri> filesUriList = new ArrayList<>(); + final String selection = String.format( + "%s = '%s' AND %s = %s", + "media_grants." + MediaGrants.OWNER_PACKAGE_NAME_COLUMN, + packageName, + "media_grants." + MediaGrants.PACKAGE_USER_ID_COLUMN, + Integer.toString(packageUserId)); + SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); + queryBuilder.setDistinct(true); + queryBuilder.setTables(MEDIA_GRANTS_AND_FILES_JOIN_TABLE_NAME); + try (Cursor c = queryBuilder.query(db, + new String[]{DATA, FILE_ID_COLUMN}, + selection, + null, null, null, null, null, null)) { + while (c.moveToNext()) { + final String file_path = c.getString(c.getColumnIndexOrThrow(DATA)); + final Integer file_id = c.getInt(c.getColumnIndexOrThrow(FILE_ID_COLUMN)); + filesUriList.add(FileUtils.getContentUriForPath( + file_path).buildUpon().appendPath(String.valueOf(file_id)).build()); + } + return filesUriList; + } + }); + } + + /** * Removes any existing media grants for the given package from the external database. This will * not alter the files or file metadata themselves. * diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java index ced5445e4..1cd80b437 100644 --- a/src/com/android/providers/media/MediaProvider.java +++ b/src/com/android/providers/media/MediaProvider.java @@ -1311,7 +1311,7 @@ public class MediaProvider extends ContentProvider { mPickerSyncController = PickerSyncController.initialize(context, mPickerDbFacade, mConfigStore); - mPickerDataLayer = new PickerDataLayer(context, mPickerDbFacade, mPickerSyncController, + mPickerDataLayer = PickerDataLayer.create(context, mPickerDbFacade, mPickerSyncController, mConfigStore); mPickerUriResolver = new PickerUriResolver(context, mPickerDbFacade, mProjectionHelper); @@ -1321,9 +1321,6 @@ public class MediaProvider extends ContentProvider { mTranscodeHelper = new TranscodeHelperNoOp(); } - // Create dir for redacted and picker URI paths. - buildPrimaryVolumeFile(uidToUserId(MY_UID), getRedactedRelativePath()).mkdirs(); - final IntentFilter packageFilter = new IntentFilter(); packageFilter.setPriority(10); packageFilter.addDataScheme("package"); @@ -6810,10 +6807,15 @@ public class MediaProvider extends ContentProvider { return bundle; } case MediaStore.IS_CURRENT_CLOUD_PROVIDER_CALL: { - final boolean isEnabled = mPickerSyncController.isProviderEnabled(arg, - Binder.getCallingUid()); - Bundle bundle = new Bundle(); + boolean isEnabled = false; + + if (mConfigStore.isCloudMediaInPhotoPickerEnabled()) { + isEnabled = + mPickerSyncController.isProviderEnabled( + arg, Binder.getCallingUid()); + } + bundle.putBoolean(MediaStore.EXTRA_CLOUD_PROVIDER_RESULT, isEnabled); return bundle; } @@ -10722,8 +10724,7 @@ public class MediaProvider extends ContentProvider { ForegroundThread.getExecutor().execute(() -> { mExternalDatabase.runWithTransaction((db) -> { - ensureDefaultFolders(volume, db); - ensureThumbnailsValid(volume, db); + ensureNecessaryFolders(volume, db); return null; }); @@ -10785,6 +10786,22 @@ public class MediaProvider extends ContentProvider { if (LOGV) Log.v(TAG, "Detached volume: " + volumeName); } + private void ensureNecessaryFolders(MediaVolume volume, SQLiteDatabase db) { + ensureDefaultFolders(volume, db); + ensureThumbnailsValid(volume, db); + + // Create redacted directories + if (MediaStore.VOLUME_EXTERNAL_PRIMARY.equalsIgnoreCase(volume.getName())) { + // Create dir for redacted and picker URI paths. + File redactedRelativePath = buildPrimaryVolumeFile(uidToUserId(MY_UID), + getRedactedRelativePath()); + if (!redactedRelativePath.exists() && !redactedRelativePath.mkdirs()) { + // We should always be able to create these directories from MediaProvider + Log.wtf(TAG, "Couldn't create redacted path for " + UserHandle.myUserId()); + } + } + } + @GuardedBy("mAttachedVolumes") private final ArraySet<MediaVolume> mAttachedVolumes = new ArraySet<>(); @GuardedBy("mCustomCollators") diff --git a/src/com/android/providers/media/photopicker/DialogUtils.java b/src/com/android/providers/media/photopicker/DialogUtils.java new file mode 100644 index 000000000..9f94aeff5 --- /dev/null +++ b/src/com/android/providers/media/photopicker/DialogUtils.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.media.photopicker; + +import android.app.AlertDialog; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import androidx.appcompat.app.AppCompatActivity; + +import com.android.providers.media.R; + +/** + * Dialog box to display custom alert or error messages + */ +public class DialogUtils extends AppCompatActivity { + /** + * Custom dialog box with single button to display title and single error message + */ + public static void showDialog(Context context, String title, String message) { + View customView = + LayoutInflater.from(context).inflate(R.layout.error_dialog, null); + + TextView dialogTitle = customView.findViewById(R.id.title); + TextView dialogMessage = customView.findViewById(R.id.message); + Button gotItButton = customView.findViewById(R.id.okButton); + dialogTitle.setText(title); + dialogMessage.setText(message); + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setView(customView); + builder.setCancelable(false); // Prevent dismiss when clicking outside + final AlertDialog dialog = builder.create(); + + gotItButton.setOnClickListener(v -> { + dialog.dismiss(); // Close the dialog + }); + dialog.show(); + } +} diff --git a/src/com/android/providers/media/photopicker/PhotoPickerActivity.java b/src/com/android/providers/media/photopicker/PhotoPickerActivity.java index b64ba1f8a..1cdc56c6f 100644 --- a/src/com/android/providers/media/photopicker/PhotoPickerActivity.java +++ b/src/com/android/providers/media/photopicker/PhotoPickerActivity.java @@ -65,6 +65,8 @@ import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.FragmentManager; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; @@ -73,6 +75,7 @@ import com.android.providers.media.R; import com.android.providers.media.photopicker.data.PickerResult; import com.android.providers.media.photopicker.data.Selection; import com.android.providers.media.photopicker.data.UserIdManager; +import com.android.providers.media.photopicker.data.model.Item; import com.android.providers.media.photopicker.data.model.UserId; import com.android.providers.media.photopicker.ui.TabContainerFragment; import com.android.providers.media.photopicker.util.LayoutModeUtils; @@ -115,6 +118,10 @@ public class PhotoPickerActivity extends AppCompatActivity { private Toolbar mToolbar; private CrossProfileListeners mCrossProfileListeners; + @NonNull + private final MutableLiveData<Boolean> mIsItemPhotoGridViewChanged = + new MutableLiveData<>(false); + @ColorInt private int mDefaultBackgroundColor; @@ -527,13 +534,17 @@ public class PhotoPickerActivity extends AppCompatActivity { return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; } + public LiveData<Boolean> isItemPhotoGridViewChanged() { + return mIsItemPhotoGridViewChanged; + } + public void setResultAndFinishSelf() { logPickerSelectionConfirmed(mSelection.getSelectedItems().size()); - if (shouldPreloadSelectedItems()) { final var uris = PickerResult.getPickerUrisForItems(mSelection.getSelectedItems()); mPreloaderInstanceHolder.preloader = SelectedMediaPreloader.preload(/* activity */ this, uris); + deSelectUnavailableMedia(mPreloaderInstanceHolder.preloader); subscribeToSelectedMediaPreloader(mPreloaderInstanceHolder.preloader); } else { setResultAndFinishSelfInternal(); @@ -611,6 +622,30 @@ public class PhotoPickerActivity extends AppCompatActivity { }); } + // This method is responsible for deselecting all unavailable items from selection list + // when user tries selecting unavailable could only media (not cached) while offline + private void deSelectUnavailableMedia(@NonNull SelectedMediaPreloader preloader) { + preloader.getUnavailableMediaIndexes().observe( + /* lifecycleOwner */ PhotoPickerActivity.this, + unavailableMediaIndexes -> { + if (unavailableMediaIndexes.size() > 0) { + // To notify the fragment to uncheck the unavailable items at UI those are + // no longer available in the selection list. + mIsItemPhotoGridViewChanged.postValue(true); + // Displaying error dialog with an error message when the user tries + // to add unavailable cloud only media (not cached) while offline. + DialogUtils.showDialog(this, + getResources().getString(R.string.dialog_error_title), + getResources().getString(R.string.dialog_error_message)); + + List<Item> selectedItems = mSelection.getSelectedItems(); + for (var mediaIndex : unavailableMediaIndexes) { + mSelection.removeSelectedItem(selectedItems.get(mediaIndex)); + } + } + }); + } + /** * NOTE: this may wrongly return {@code false} if called before {@link PickerViewModel} had a * chance to fetch the authority and the account of the current @@ -840,15 +875,32 @@ public class PhotoPickerActivity extends AppCompatActivity { * Reset to Photo Picker initial launch state (Photos grid tab) in personal profile mode. */ private void resetToPersonalProfile() { + // Clear all the fragments in the FragmentManager + final FragmentManager fragmentManager = getSupportFragmentManager(); + fragmentManager.popBackStackImmediate(/* name */ null, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + + // Reset all content to the personal profile mPickerViewModel.resetToPersonalProfile(); + + // Set up the fragments same as the initial launch state setupInitialLaunchState(); } /** * Reset to Photo Picker initial launch state (Photos grid tab) in the current profile mode. */ - private void resetInCurrentProfile() { + @VisibleForTesting + public void resetInCurrentProfile() { + // Clear all the fragments in the FragmentManager + final FragmentManager fragmentManager = getSupportFragmentManager(); + fragmentManager.popBackStackImmediate(/* name */ null, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + + // Reset all content in the current profile mPickerViewModel.resetAllContentInCurrentProfile(); + + // Set up the fragments same as the initial launch state setupInitialLaunchState(); } @@ -978,11 +1030,6 @@ public class PhotoPickerActivity extends AppCompatActivity { } private void switchToPersonalProfileInitialLaunchState() { - final FragmentManager fragmentManager = getSupportFragmentManager(); - // Clear all back stacks in FragmentManager - fragmentManager.popBackStackImmediate(/* name */ null, - FragmentManager.POP_BACK_STACK_INCLUSIVE); - // We reset the state of the PhotoPicker as we do not want to make any // assumptions on the state of the PhotoPicker when it was in Work Profile mode. resetToPersonalProfile(); diff --git a/src/com/android/providers/media/photopicker/PickerDataLayer.java b/src/com/android/providers/media/photopicker/PickerDataLayer.java index 51543917a..b479b45b1 100644 --- a/src/com/android/providers/media/photopicker/PickerDataLayer.java +++ b/src/com/android/providers/media/photopicker/PickerDataLayer.java @@ -26,6 +26,8 @@ import static android.provider.MediaStore.MY_UID; import static com.android.providers.media.PickerUriResolver.getAlbumUri; import static com.android.providers.media.PickerUriResolver.getMediaCollectionInfoUri; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.IMMEDIATE_ALBUM_SYNC_WORK_NAME; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.IMMEDIATE_LOCAL_SYNC_WORK_NAME; import static java.util.Objects.requireNonNull; @@ -55,6 +57,7 @@ import com.android.providers.media.photopicker.metrics.NonUiEventLogger; import com.android.providers.media.photopicker.sync.PickerSyncManager; import com.android.providers.media.photopicker.sync.SyncTracker; import com.android.providers.media.photopicker.sync.SyncTrackerRegistry; +import com.android.providers.media.util.ForegroundThread; import java.util.ArrayList; import java.util.Arrays; @@ -64,6 +67,8 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -80,8 +85,18 @@ public class PickerDataLayer { public static final String QUERY_DATE_TAKEN_BEFORE_MS = "android:query-date-taken-before-ms"; + public static final String QUERY_LOCAL_ID_SELECTION = "android:query-local-id-selection"; + public static final String QUERY_ROW_ID = "android:query-row-id"; + // Thread pool size should be at least equal to the number of unique work requests in + // {@link PickerSyncManager} to ensure that any request type is not blocked on other request + // types. It is advisable to use unique work requests because in case the number of queued + // requests grows, they should not block other work requests. + private static final int WORK_MANAGER_THREAD_POOL_SIZE = 5; + @Nullable + private static volatile Executor sWorkManagerExecutor; + @NonNull private final Context mContext; @NonNull @@ -95,22 +110,31 @@ public class PickerDataLayer { @NonNull private final ConfigStore mConfigStore; - public PickerDataLayer(@NonNull Context context, @NonNull PickerDbFacade dbFacade, - @NonNull PickerSyncController syncController, @NonNull ConfigStore configStore) { - this(context, dbFacade, syncController, configStore, /* schedulePeriodicSyncs */ true); - } - @VisibleForTesting public PickerDataLayer(@NonNull Context context, @NonNull PickerDbFacade dbFacade, @NonNull PickerSyncController syncController, @NonNull ConfigStore configStore, - boolean schedulePeriodicSyncs) { + @NonNull PickerSyncManager syncManager) { mContext = requireNonNull(context); mDbFacade = requireNonNull(dbFacade); mSyncController = requireNonNull(syncController); mLocalProvider = requireNonNull(dbFacade.getLocalProvider()); mConfigStore = requireNonNull(configStore); - mSyncManager = new PickerSyncManager( - getWorkManager(), configStore, schedulePeriodicSyncs); + mSyncManager = syncManager; + + // Add a subscriber to config store changes to monitor the allowlist. + mConfigStore.addOnChangeListener( + ForegroundThread.getExecutor(), + this::validateCurrentCloudProviderOnAllowlistChange); + } + + /** + * Create a new instance of PickerDataLayer. + */ + public static PickerDataLayer create(@NonNull Context context, @NonNull PickerDbFacade dbFacade, + @NonNull PickerSyncController syncController, @NonNull ConfigStore configStore) { + PickerSyncManager syncManager = new PickerSyncManager( + getWorkManager(context), context, configStore, /* schedulePeriodicSyncs */ true); + return new PickerDataLayer(context, dbFacade, syncController, configStore, syncManager); } /** @@ -157,7 +181,8 @@ public class PickerDataLayer { syncAllMedia(isLocalOnly); } else { // Wait for local sync to finish indefinitely - waitForSync(SyncTrackerRegistry.getLocalSyncTracker()); + waitForSync(SyncTrackerRegistry.getLocalSyncTracker(), + IMMEDIATE_LOCAL_SYNC_WORK_NAME); Log.i(TAG, "Local sync is complete"); // Wait for on cloud sync with timeout @@ -188,7 +213,8 @@ public class PickerDataLayer { if (shouldSyncBeforePickerQuery()) { mSyncController.syncAlbumMedia(albumId, isLocal(albumAuthority)); } else { - waitForSync(SyncTrackerRegistry.getAlbumSyncTracker(isLocal(albumAuthority))); + waitForSync(SyncTrackerRegistry.getAlbumSyncTracker(isLocal(albumAuthority)), + IMMEDIATE_ALBUM_SYNC_WORK_NAME); Log.i(TAG, "Album sync is complete"); } @@ -220,10 +246,58 @@ public class PickerDataLayer { } } - private void waitForSync(@NonNull SyncTracker syncTracker) { - waitForSyncWithTimeout(syncTracker, /* timeout */ null); + /** + * Will try it's best to wait for the existing sync requests to complete. It may not wait for + * new sync requests received after this method starts running. + */ + private void waitForSync(@NonNull SyncTracker syncTracker, String uniqueWorkName) { + try { + final CompletableFuture<Void> completableFuture = + CompletableFuture.allOf( + syncTracker.pendingSyncFutures().toArray(new CompletableFuture[0])); + + waitForSync(completableFuture, uniqueWorkName, /* retryCount */ 30); + } catch (ExecutionException | InterruptedException e) { + Log.w(TAG, "Could not wait for the sync to finish: " + e); + } + } + + /** + * Wait for sync tracked by the input future to complete. In case the future takes an unusually + * long time to complete, check the relevant unique work status from Work Manager. + */ + @VisibleForTesting + public int waitForSync(@NonNull CompletableFuture<Void> completableFuture, + @NonNull String uniqueWorkName, + int retryCount) throws ExecutionException, InterruptedException { + for (; retryCount > 0; retryCount--) { + try { + completableFuture.get(/* timeout */ 3, TimeUnit.SECONDS); + return retryCount; + } catch (TimeoutException e) { + if (mSyncManager.isUniqueWorkPending(uniqueWorkName)) { + Log.i(TAG, "Waiting for the sync again." + + " Unique work name: " + uniqueWorkName + + " Retry count: " + retryCount); + } else { + Log.e(TAG, "Either immediate unique work is complete and the sync futures " + + "were not cleared, or a proactive sync might be blocking the query. " + + "Unblocking the query now for " + uniqueWorkName); + return retryCount; + } + } + } + + if (retryCount == 0) { + Log.e(TAG, "Retry count exhausted, could not wait for sync anymore."); + } + return retryCount; } + /** + * Will wait for the existing sync requests to complete till the provided timeout. It may + * not wait for new sync requests received after this method starts running. + */ private boolean waitForSyncWithTimeout( @NonNull SyncTracker syncTracker, @Nullable Long timeoutInMillis) { @@ -231,14 +305,10 @@ public class PickerDataLayer { final CompletableFuture<Void> completableFuture = CompletableFuture.allOf( syncTracker.pendingSyncFutures().toArray(new CompletableFuture[0])); - if (timeoutInMillis == null) { - completableFuture.get(); - } else { - completableFuture.get(timeoutInMillis, TimeUnit.MILLISECONDS); - } + completableFuture.get(timeoutInMillis, TimeUnit.MILLISECONDS); return true; } catch (ExecutionException | InterruptedException | TimeoutException e) { - Log.w(TAG, "Could not wait for the sync to finish: " + e); + Log.w(TAG, "Could not wait for the sync with timeout to finish: " + e); return false; } } @@ -288,7 +358,8 @@ public class PickerDataLayer { cursorExtra.putString(MediaStore.EXTRA_LOCAL_PROVIDER, mLocalProvider); // Favorites and Videos are merged albums. - final Cursor mergedAlbums = mDbFacade.getMergedAlbums(queryExtras.toQueryFilter()); + final Cursor mergedAlbums = mDbFacade.getMergedAlbums(queryExtras.toQueryFilter(), + cloudProvider); if (mergedAlbums != null) { cursors.add(mergedAlbums); } @@ -445,7 +516,7 @@ public class PickerDataLayer { if (!syncRequestExtras.shouldSyncMergedAlbum()) { mSyncManager.syncAlbumMediaForProviderImmediately( syncRequestExtras.getAlbumId(), - isLocal(syncRequestExtras.getAlbumAuthority())); + syncRequestExtras.getAlbumAuthority()); } } } @@ -473,7 +544,13 @@ public class PickerDataLayer { * local providers. */ public void handleMediaEventNotification() { - mSyncManager.syncAllMediaProactively(); + try { + mSyncManager.syncAllMediaProactively(); + } catch (RuntimeException e) { + // Catch any unchecked exceptions so that critical paths in MP that call this method are + // not affected by Picker related issues. + Log.e(TAG, "Could not handle media event notification ", e); + } } public static class AccountInfo { @@ -589,7 +666,7 @@ public class PickerDataLayer { * @return a {@link WorkManager} object that can be used to run work requests. */ @NonNull - private WorkManager getWorkManager() { + private static WorkManager getWorkManager(Context mContext) { if (!WorkManager.isInitialized()) { Log.i(TAG, "Work manager not initialised. Attempting to initialise."); WorkManager.initialize(mContext, getWorkManagerConfiguration()); @@ -599,11 +676,24 @@ public class PickerDataLayer { @NonNull private static Configuration getWorkManagerConfiguration() { + ensureWorkManagerExecutor(); return new Configuration.Builder() .setMinimumLoggingLevel(Log.INFO) + .setExecutor(sWorkManagerExecutor) .build(); } + private static void ensureWorkManagerExecutor() { + if (sWorkManagerExecutor == null) { + synchronized (PickerDataLayer.class) { + if (sWorkManagerExecutor == null) { + sWorkManagerExecutor = Executors + .newFixedThreadPool(WORK_MANAGER_THREAD_POOL_SIZE); + } + } + } + } + /** * For cloud feature enabled scenarios, sync request is sent from the * MediaStore.PICKER_MEDIA_INIT_CALL method call once when a fresh grid needs to be filled @@ -614,4 +704,27 @@ public class PickerDataLayer { private boolean shouldSyncBeforePickerQuery() { return !mConfigStore.isCloudMediaInPhotoPickerEnabled(); } + + /** + * Checks the current allowed list of Cloud Provider packages, and ensures that the currently + * set provider is a member of the allowlist. In the event the current Cloud Provider is not on + * the list, the current Cloud Provider is removed. + */ + private void validateCurrentCloudProviderOnAllowlistChange() { + + List<String> currentAllowlist = mConfigStore.getAllowedCloudProviderPackages(); + String currentCloudProvider = mSyncController.getCurrentCloudProviderInfo().packageName; + + if (!currentAllowlist.contains(currentCloudProvider)) { + Log.d( + TAG, + String.format( + "Cloud provider allowlist was changed, and the current cloud provider" + + " is no longer on the allowlist." + + " Allowlist: %s" + + " Current Provider: %s", + currentAllowlist.toString(), currentCloudProvider)); + mSyncController.notifyPackageRemoval(currentCloudProvider); + } + } } diff --git a/src/com/android/providers/media/photopicker/PickerSyncController.java b/src/com/android/providers/media/photopicker/PickerSyncController.java index 347be1fde..c12bdaa81 100644 --- a/src/com/android/providers/media/photopicker/PickerSyncController.java +++ b/src/com/android/providers/media/photopicker/PickerSyncController.java @@ -138,6 +138,9 @@ public class PickerSyncController { private final String mLocalProvider; private final Object mCloudSyncLock = new Object(); + private final Object mCloudAlbumSyncLock = new Object(); + + // TODO(b/278562157): If there is a dependency on the sync process, always acquire the // {@link mCloudSyncLock} before {@link mCloudProviderLock} to avoid deadlock. private final Object mCloudProviderLock = new Object(); @@ -215,6 +218,8 @@ public class PickerSyncController { mDbFacade = dbFacade; mLocalProvider = localProvider; + // Listen to the device config, and try to enable cloud features when the config changes. + mConfigStore.addOnChangeListener(BackgroundThread.getExecutor(), this::initCloudProvider); initCloudProvider(); } @@ -256,6 +261,14 @@ public class PickerSyncController { } /** + * Returns the sync lock object for Cloud albums. + * @return the lock object for protecting synchronized code related to cloud albums. + */ + public Object getCloudAlbumSyncLock() { + return mCloudAlbumSyncLock; + } + + /** * Syncs the local and currently enabled cloud {@link CloudMediaProvider} instances */ public void syncAllMedia() { @@ -290,6 +303,7 @@ public class PickerSyncController { * Syncs the cloud media */ public void syncAllMediaFromCloudProvider() { + synchronized (mCloudSyncLock) { final String cloudProvider = getCloudProvider(); @@ -305,10 +319,6 @@ public class PickerSyncController { + ". The cloud provider may have changed during the sync, or only a" + " partial sync was completed."); } - - // Reset the album_media table every time we sync all media - // TODO(258765155): do we really need to reset for both providers? - resetAlbumMedia(); } } @@ -318,8 +328,12 @@ public class PickerSyncController { */ public void syncAlbumMedia(String albumId, boolean isLocal) { if (isLocal) { + executeSyncAlbumReset(getLocalProvider(), isLocal, albumId); syncAlbumMediaFromLocalProvider(albumId); } else { + synchronized (mCloudAlbumSyncLock) { + executeSyncAlbumReset(getCloudProvider(), isLocal, albumId); + } syncAlbumMediaFromCloudProvider(albumId); } } @@ -336,20 +350,12 @@ public class PickerSyncController { * Syncs album media from the currently enabled cloud {@link CloudMediaProvider}. */ public void syncAlbumMediaFromCloudProvider(@NonNull String albumId) { - synchronized (mCloudSyncLock) { + synchronized (mCloudAlbumSyncLock) { syncAlbumMediaFromProvider(getCloudProvider(), /* isLocal */ false, albumId, /* enforcePagedSync*/ true); } } - private void resetAlbumMedia() { - executeSyncAlbumReset(mLocalProvider, /* isLocal */ true, /* albumId */ null); - - synchronized (mCloudSyncLock) { - executeSyncAlbumReset(getCloudProvider(), /* isLocal */ false, /* albumId */ null); - } - } - /** * Resets media library previously synced from the current {@link CloudMediaProvider} as well * as the {@link #mLocalProvider local provider}. @@ -440,12 +446,6 @@ public class PickerSyncController { Log.v(TAG, "Thread=" + Thread.currentThread() + "; Stacktrace:", new Throwable()); } - if (!mConfigStore.isCloudMediaInPhotoPickerEnabled()) { - Log.w(TAG, "Ignoring a request to set the CloudMediaProvider (" + authority + ") " - + "since the Cloud-Media-in-Photo-Picker feature is disabled"); - return false; - } - synchronized (mCloudProviderLock) { if (Objects.equals(mCloudProviderInfo.authority, authority)) { Log.w(TAG, "Cloud provider already set: " + authority); @@ -618,8 +618,6 @@ public class PickerSyncController { Trace.beginSection(traceSectionName("syncAlbumMediaFromProvider", isLocal)); try { - executeSyncAlbumReset(authority, isLocal, albumId); - if (authority != null) { executeSyncAddAlbum(authority, isLocal, albumId, queryArgs, instanceId); } @@ -628,6 +626,8 @@ public class PickerSyncController { // occurred in fetching all the album_media since incremental sync is not supported. // A full sync is therefore unlikely to resolve any issue Log.e(TAG, "Failed to sync album media", e); + } catch (RequestObsoleteException e) { + Log.e(TAG, "Failed to sync all album media because authority has changed: ", e); } finally { Trace.endSection(); } @@ -785,18 +785,29 @@ public class PickerSyncController { } /** - * Queries the provider and writes the data returned to the db. - * - * <p> Also validates the cursor returned from provider has expected extras of not. + * Queries the provider and adds media to the picker database. * + * @param authority Provider's authority + * @param isLocal Whether this is the local provider or not + * @param expectedMediaCollectionId The MediaCollectionId from the last sync point. * @param isIncrementalSync If true, {@link CloudMediaProviderContract#EXTRA_SYNC_GENERATION} - * should be honoured by the provider. - * @param enforcePagedSync If true, {@link CloudMediaProviderContract#EXTRA_PAGE_SIZE} should - * be honoured by the provider. + * should be honoured by the provider. + * @param enforcePagedSync If true, {@link CloudMediaProviderContract#EXTRA_PAGE_SIZE} should be + * honoured by the provider. + * @param queryArgs Query arguments to pass in query. + * @param instanceId Metrics related Picker session instance Id. + * @throws RequestObsoleteException When the sync is interrupted due to the provider + * changing. */ - private void executeSyncAdd(String authority, boolean isLocal, - String expectedMediaCollectionId, boolean isIncrementalSync, boolean enforcePagedSync, - Bundle queryArgs, InstanceId instanceId) { + private void executeSyncAdd( + String authority, + boolean isLocal, + String expectedMediaCollectionId, + boolean isIncrementalSync, + boolean enforcePagedSync, + Bundle queryArgs, + InstanceId instanceId) + throws RequestObsoleteException { final Uri uri = getMediaUri(authority); final List<String> expectedHonoredArgs = new ArrayList<>(); if (isIncrementalSync) { @@ -821,7 +832,8 @@ public class PickerSyncController { queryArgs, resumeKey, OPERATION_ADD_MEDIA, - authority); + authority, + isLocal); NonUiEventLogger.logPickerAddMediaSyncCompletion(instanceId, MY_UID, authority, syncedItems); } finally { @@ -829,8 +841,24 @@ public class PickerSyncController { } } - private void executeSyncAddAlbum(String authority, boolean isLocal, - String albumId, Bundle queryArgs, InstanceId instanceId) { + /** + * Queries the provider to sync media from the given albumId into the picker database. + * + * @param authority Provider's authority + * @param isLocal Whether this is the local provider or not + * @param albumId the Id of the album to sync + * @param queryArgs Query arguments to pass in query. + * @param instanceId Metrics related Picker session instance Id. + * @throws RequestObsoleteException When the sync is interrupted due to the provider + * changing. + */ + private void executeSyncAddAlbum( + String authority, + boolean isLocal, + String albumId, + Bundle queryArgs, + InstanceId instanceId) + throws RequestObsoleteException { final Uri uri = getMediaUri(authority); Log.i(TAG, "Executing SyncAddAlbum. " @@ -843,9 +871,17 @@ public class PickerSyncController { // We don't need to validate the mediaCollectionId for album_media sync since it's // always a full sync - int syncedItems = executePagedSync(uri, /* mediaCollectionId */ null, - List.of(EXTRA_ALBUM_ID), queryArgs, resumeKey, OPERATION_ADD_ALBUM, authority, - albumId); + int syncedItems = + executePagedSync( + uri, /* mediaCollectionId */ + null, + List.of(EXTRA_ALBUM_ID), + queryArgs, + resumeKey, + OPERATION_ADD_ALBUM, + authority, + isLocal, + albumId); NonUiEventLogger.logPickerAddAlbumMediaSyncCompletion(instanceId, MY_UID, authority, syncedItems); } finally { @@ -853,8 +889,24 @@ public class PickerSyncController { } } - private void executeSyncRemove(String authority, boolean isLocal, - String mediaCollectionId, Bundle queryArgs, InstanceId instanceId) { + /** + * Queries the provider and syncs removed media with the picker database. + * + * @param authority Provider's authority + * @param isLocal Whether this is the local provider or not + * @param mediaCollectionId The last synced media collection id + * @param queryArgs Query arguments to pass in query. + * @param instanceId Metrics related Picker session instance Id. + * @throws RequestObsoleteException When the sync is interrupted due to the provider + * changing. + */ + private void executeSyncRemove( + String authority, + boolean isLocal, + String mediaCollectionId, + Bundle queryArgs, + InstanceId instanceId) + throws RequestObsoleteException { final Uri uri = getDeletedMediaUri(authority); Log.i(TAG, "Executing SyncRemove. isLocal: " + isLocal + ". authority: " + authority); @@ -863,9 +915,16 @@ public class PickerSyncController { Trace.beginSection(traceSectionName("executeSyncRemove", isLocal)); try { - int syncedItems = executePagedSync(uri, mediaCollectionId, - List.of(EXTRA_SYNC_GENERATION), queryArgs, resumeKey, OPERATION_REMOVE_MEDIA, - authority); + int syncedItems = + executePagedSync( + uri, + mediaCollectionId, + List.of(EXTRA_SYNC_GENERATION), + queryArgs, + resumeKey, + OPERATION_REMOVE_MEDIA, + authority, + isLocal); NonUiEventLogger.logPickerRemoveMediaSyncCompletion(instanceId, MY_UID, authority, syncedItems); } finally { @@ -1002,7 +1061,7 @@ public class PickerSyncController { */ private void rememberNextPageToken(@Nullable String token, String resumeKey) { - synchronized (mCloudSyncLock) { + synchronized (mCloudProviderLock) { final SharedPreferences.Editor editor = mSyncPrefs.edit(); if (token == null) { Log.d(TAG, String.format("Clearing next page token for key: %s", resumeKey)); @@ -1176,6 +1235,8 @@ public class PickerSyncController { * between pages. * @param op The DbWriteOperation type. {@link OperationType} * @param authority The authority string of the provider to sync with. + * @throws RequestObsoleteException When the sync is interrupted due to the provider + * changing. * @return the total number of rows synced. */ private int executePagedSync( @@ -1185,7 +1246,8 @@ public class PickerSyncController { Bundle queryArgs, @Nullable String resumeKey, @OperationType int op, - String authority) { + String authority, + Boolean isLocal) throws RequestObsoleteException { return executePagedSync( uri, expectedMediaCollectionId, @@ -1194,6 +1256,7 @@ public class PickerSyncController { resumeKey, op, authority, + isLocal, /* albumId=*/ null); } @@ -1212,6 +1275,8 @@ public class PickerSyncController { * @param op The DbWriteOperation type. {@link OperationType} * @param authority The authority string of the provider to sync with. * @param albumId A {@link Nullable} albumId for album related operations. + * @throws RequestObsoleteException When the sync is interrupted due to the provider + * changing. * @return the total number of rows synced. */ private int executePagedSync( @@ -1222,7 +1287,8 @@ public class PickerSyncController { @Nullable String resumeKey, @OperationType int op, String authority, - @Nullable String albumId) { + Boolean isLocal, + @Nullable String albumId) throws RequestObsoleteException { Trace.beginSection(traceSectionName("executePagedSync")); try { @@ -1241,33 +1307,55 @@ public class PickerSyncController { do { String updateDateTakenMs = null; - try (PickerDbFacade.DbWriteOperation operation = - beginPagedOperation(op, authority, albumId)) { - - if (nextPageToken != null) { - queryArgs.putString(EXTRA_PAGE_TOKEN, nextPageToken); - } - - try (Cursor cursor = query(uri, queryArgs)) { - nextPageToken = - validateCursor( - cursor, - expectedMediaCollectionId, - expectedHonoredArgs, - tokens); + if (nextPageToken != null) { + queryArgs.putString(EXTRA_PAGE_TOKEN, nextPageToken); + } + try (Cursor cursor = query(uri, queryArgs)) { + nextPageToken = + validateCursor( + cursor, + expectedMediaCollectionId, + expectedHonoredArgs, + tokens); + try (PickerDbFacade.DbWriteOperation operation = + beginPagedOperation(op, authority, albumId)) { int writeCount = operation.execute(cursor); + if (!isLocal) { + // Ensure the cloud provider hasn't change out from underneath the + // running sync. If it has, we need to stop syncing. + String currentCloudProvider = getCloudProvider(); + if (TextUtils.isEmpty(currentCloudProvider) + || !currentCloudProvider.equals(authority)) { + + throw new RequestObsoleteException( + String.format( + "Aborting sync: the CloudProvider seems to have" + + " changed mid-sync. Old: %s Current: %s", + authority, currentCloudProvider)); + } + } + + operation.setSuccess(); totalRowcount += writeCount; - // Before the cursor is closed pull the date taken ms for the first row. - updateDateTakenMs = getFirstDateTakenMsInCursor(cursor); + if (cursor.getCount() > 0) { + // Before the cursor is closed pull the date taken ms for the first row. + updateDateTakenMs = getFirstDateTakenMsInCursor(cursor); + + // If the cursor count is not null and the date taken field is not + // present in the cursor, fallback on the operation to provide the date + // taken. + if (updateDateTakenMs == null) { + updateDateTakenMs = getFirstDateTakenMsFromOperation(operation); + } + } } - operation.setSuccess(); - } catch (IllegalArgumentException ex) { - Log.e(TAG, String.format("Failed to open DbWriteOperation for op: %d", op), ex); + Log.e(TAG, String.format("Failed to open DbWriteOperation for op: %d", op), + ex); return -1; } @@ -1307,14 +1395,25 @@ public class PickerSyncController { */ @Nullable private String getFirstDateTakenMsInCursor(Cursor cursor) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); + if (cursor.moveToFirst()) { return getCursorString(cursor, MediaColumns.DATE_TAKEN_MILLIS); } return null; } /** + * Extracts the first row's date taken from the operation. Note that all functions may not + * implement this method. + */ + private String getFirstDateTakenMsFromOperation(PickerDbFacade.DbWriteOperation op) { + final long firstDateTakenMillis = op.getFirstDateTakenMillis(); + + return firstDateTakenMillis == Long.MIN_VALUE + ? null + : Long.toString(firstDateTakenMillis); + } + + /** * Assembles a ContentObserver notification uri for the given operation. * * @param op {@link OperationType} the operation to notify has completed. diff --git a/src/com/android/providers/media/photopicker/SelectedMediaPreloader.java b/src/com/android/providers/media/photopicker/SelectedMediaPreloader.java index 661345bdb..7419f01cf 100644 --- a/src/com/android/providers/media/photopicker/SelectedMediaPreloader.java +++ b/src/com/android/providers/media/photopicker/SelectedMediaPreloader.java @@ -73,6 +73,9 @@ class SelectedMediaPreloader { @NonNull private final MutableLiveData<Boolean> mIsFinishedLiveData = new MutableLiveData<>(false); @NonNull + private final MutableLiveData<List<Integer>> mUnavailableMediaIndexes = + new MutableLiveData<>(new ArrayList<>()); + @NonNull private final ContentResolver mContentResolver; /** @@ -107,24 +110,24 @@ class SelectedMediaPreloader { Trace.beginAsyncSection(TRACE_SECTION_NAME, /* cookie */ preloader.hashCode()); - final var dialog = createProgressDialog(activity, items); + final var dialog = createProgressDialog(activity, items, context); preloader.mIsFinishedLiveData.observeForever(new Observer<>() { @Override public void onChanged(Boolean isFinished) { if (isFinished) { preloader.mIsFinishedLiveData.removeObserver(this); - dialog.dismiss(); - Trace.endAsyncSection(TRACE_SECTION_NAME, /* cookie */ preloader.hashCode()); } } }); + preloader.mFinishedCountLiveData.observeForever(new Observer<>() { @Override public void onChanged(Integer finishedCount) { if (finishedCount == count) { preloader.mFinishedCountLiveData.removeObserver(this); + dialog.dismiss(); } // "X of Y ready" final String message = context.getString( @@ -155,18 +158,28 @@ class SelectedMediaPreloader { return mIsFinishedLiveData; } + @NonNull + LiveData<List<Integer>> getUnavailableMediaIndexes() { + return mUnavailableMediaIndexes; + } + /** * This method is intentionally {@code private}: clients should use static * {@link #preload(Context, List)} method. */ @UiThread private void start(@NonNull Executor executor) { - for (var item : mItems) { + List<Integer> unavailableMediaIndexes = new ArrayList<>(); + for (int index = 0; index < mItems.size(); index++) { + int currIndex = index; // Off-loading to an Executor (presumable backed up by a thread pool) executor.execute(new Runnable() { @Override public void run() { - openFileDescriptor(item); + boolean isOpenedSuccessfully = openFileDescriptor(mItems.get(currIndex)); + if (!isOpenedSuccessfully) { + unavailableMediaIndexes.add(currIndex); + } final int preloadedCount = mFinishedCount.incrementAndGet(); if (DEBUG) { @@ -175,7 +188,12 @@ class SelectedMediaPreloader { if (preloadedCount == mCount) { // Don't need to "synchronize" here: mCount is our final value for // preloadedCount, it won't be changing anymore. - mIsFinishedLiveData.postValue(true); + if (unavailableMediaIndexes.size() == 0) { + mIsFinishedLiveData.postValue(true); + } else { + mUnavailableMediaIndexes.postValue(unavailableMediaIndexes); + mIsFinishedLiveData.postValue(false); + } } // In order to prevent race conditions where we may "post" a lower value after @@ -190,7 +208,8 @@ class SelectedMediaPreloader { } @Nullable - private void openFileDescriptor(@NonNull Uri uri) { + private Boolean openFileDescriptor(@NonNull Uri uri) { + Boolean isOpenedSuccessfully = true; long start = 0; if (DEBUG) { Log.d(TAG, "openFileDescriptor() START, " + Thread.currentThread() + ", " + uri); @@ -201,6 +220,7 @@ class SelectedMediaPreloader { try { mContentResolver.openAssetFileDescriptor(uri, "r"); } catch (FileNotFoundException e) { + isOpenedSuccessfully = false; Log.w(TAG, "Could not open FileDescriptor for " + uri, e); } finally { Trace.endSection(); @@ -211,22 +231,27 @@ class SelectedMediaPreloader { + ", " + uri); } } + return isOpenedSuccessfully; } @NonNull private static AlertDialog createProgressDialog( - @NonNull Activity activity, @NonNull List<Uri> selectedMedia) { - return ProgressDialog.show(activity, - /* tile */ "Preparing your selected media", - /* message */ "0 of " + selectedMedia.size() + " ready.", - /* indeterminate */ true); + @NonNull Activity activity, @NonNull List<Uri> selectedMedia, Context context) { + ProgressDialog dialog = new ProgressDialog(activity, + R.style.SelectedMediaPreloaderDialogTheme); + dialog.setTitle(/* title */ context.getString(R.string.preloading_dialog_title)); + dialog.setMessage(/* message */ context.getString( + R.string.preloading_progress_message, 0, selectedMedia.size())); + dialog.setIndeterminate(/* indeterminate */ true); + dialog.show(); + return dialog; } private static void ensureExecutor() { if (sExecutor == null) { synchronized (SelectedMediaPreloader.class) { if (sExecutor == null) { - final ThreadFactory threadFactory = new ThreadFactory() { + sExecutor = Executors.newFixedThreadPool(2, new ThreadFactory() { final AtomicInteger mCount = new AtomicInteger(1); @@ -250,8 +275,7 @@ class SelectedMediaPreloader { } }; } - }; - sExecutor = Executors.newCachedThreadPool(threadFactory); + }); } } } diff --git a/src/com/android/providers/media/photopicker/data/CloudProviderQueryExtras.java b/src/com/android/providers/media/photopicker/data/CloudProviderQueryExtras.java index b569f6953..48fd6040d 100644 --- a/src/com/android/providers/media/photopicker/data/CloudProviderQueryExtras.java +++ b/src/com/android/providers/media/photopicker/data/CloudProviderQueryExtras.java @@ -18,10 +18,12 @@ package com.android.providers.media.photopicker.data; import static android.content.ContentResolver.QUERY_ARG_LIMIT; import static com.android.providers.media.photopicker.PickerDataLayer.QUERY_DATE_TAKEN_BEFORE_MS; +import static com.android.providers.media.photopicker.PickerDataLayer.QUERY_LOCAL_ID_SELECTION; import static com.android.providers.media.photopicker.PickerDataLayer.QUERY_ROW_ID; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.BOOLEAN_DEFAULT; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.INT_DEFAULT; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.LIMIT_DEFAULT; +import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.LIST_DEFAULT; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.LONG_DEFAULT; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.STRING_ARRAY_DEFAULT; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.STRING_DEFAULT; @@ -34,6 +36,8 @@ import android.provider.MediaStore; import com.android.providers.media.photopicker.PickerDataLayer; +import java.util.List; + /** * Represents the {@link CloudMediaProviderContract} extra filters from a {@link Bundle}. */ @@ -51,6 +55,8 @@ public class CloudProviderQueryExtras { private final long mDateTakenBeforeMs; private final int mRowId; + private final List<Integer> mLocalIdSelection; + private CloudProviderQueryExtras() { mAlbumId = STRING_DEFAULT; mAlbumAuthority = STRING_DEFAULT; @@ -62,13 +68,15 @@ public class CloudProviderQueryExtras { mIsVideo = BOOLEAN_DEFAULT; mIsLocalOnly = BOOLEAN_DEFAULT; mPageSize = INT_DEFAULT; - mDateTakenBeforeMs = LONG_DEFAULT; + mDateTakenBeforeMs = Long.MIN_VALUE; mRowId = INT_DEFAULT; + mLocalIdSelection = LIST_DEFAULT; } private CloudProviderQueryExtras(String albumId, String albumAuthority, String[] mimeTypes, long sizeBytes, long generation, int limit, boolean isFavorite, boolean isVideo, - boolean isLocalOnly, int pageSize, long dateTakenBeforeMs, int rowId) { + boolean isLocalOnly, int pageSize, long dateTakenBeforeMs, int rowId, + List<Integer> localIdSelection) { mAlbumId = albumId; mAlbumAuthority = albumAuthority; mMimeTypes = mimeTypes; @@ -81,6 +89,7 @@ public class CloudProviderQueryExtras { mPageSize = pageSize; mDateTakenBeforeMs = dateTakenBeforeMs; mRowId = rowId; + mLocalIdSelection = localIdSelection; } /** @@ -106,12 +115,13 @@ public class CloudProviderQueryExtras { final boolean isLocalOnly = bundle.getBoolean(PickerDataLayer.QUERY_ARG_LOCAL_ONLY, BOOLEAN_DEFAULT); final int pageSize = INT_DEFAULT; - final Long dateTakenBeforeMs = bundle.getLong(QUERY_DATE_TAKEN_BEFORE_MS, LONG_DEFAULT); + final long dateTakenBeforeMs = bundle.getLong(QUERY_DATE_TAKEN_BEFORE_MS, Long.MIN_VALUE); final int rowId = bundle.getInt(QUERY_ROW_ID, INT_DEFAULT); + final List<Integer> localIdSelection = bundle.getIntegerArrayList(QUERY_LOCAL_ID_SELECTION); return new CloudProviderQueryExtras(albumId, albumAuthority, mimeTypes, sizeBytes, generation, limit, isFavorite, isVideo, isLocalOnly, pageSize, dateTakenBeforeMs, - rowId); + rowId, localIdSelection); } public static CloudProviderQueryExtras fromCloudMediaBundle(Bundle bundle) { @@ -133,14 +143,14 @@ public class CloudProviderQueryExtras { final boolean isFavorite = BOOLEAN_DEFAULT; final boolean isVideo = BOOLEAN_DEFAULT; final boolean isLocalOnly = BOOLEAN_DEFAULT; - final Long dateTakenBeforeMs = bundle.getLong(QUERY_DATE_TAKEN_BEFORE_MS, LONG_DEFAULT); + final long dateTakenBeforeMs = bundle.getLong(QUERY_DATE_TAKEN_BEFORE_MS, Long.MIN_VALUE); final int rowId = bundle.getInt(QUERY_ROW_ID, INT_DEFAULT); final int pageSize = bundle.getInt(CloudMediaProviderContract.EXTRA_PAGE_SIZE, INT_DEFAULT); - + final List<Integer> localIdSelection = bundle.getIntegerArrayList(QUERY_LOCAL_ID_SELECTION); return new CloudProviderQueryExtras(albumId, albumAuthority, mimeTypes, sizeBytes, generation, limit, isFavorite, isVideo, isLocalOnly, pageSize, dateTakenBeforeMs, - rowId); + rowId, localIdSelection); } public PickerDbFacade.QueryFilter toQueryFilter() { @@ -153,6 +163,7 @@ public class CloudProviderQueryExtras { qfb.setIsLocalOnly(mIsLocalOnly); qfb.setDateTakenBeforeMs(mDateTakenBeforeMs); qfb.setId(mRowId); + qfb.setLocalIdSelection(mLocalIdSelection); return qfb.build(); } diff --git a/src/com/android/providers/media/photopicker/data/ItemsProvider.java b/src/com/android/providers/media/photopicker/data/ItemsProvider.java index bf640d46a..1c6f2c03b 100644 --- a/src/com/android/providers/media/photopicker/data/ItemsProvider.java +++ b/src/com/android/providers/media/photopicker/data/ItemsProvider.java @@ -22,6 +22,7 @@ import static android.provider.MediaStore.AUTHORITY; import static com.android.providers.media.PickerUriResolver.PICKER_INTERNAL_URI; import static com.android.providers.media.photopicker.PickerDataLayer.QUERY_DATE_TAKEN_BEFORE_MS; +import static com.android.providers.media.photopicker.PickerDataLayer.QUERY_LOCAL_ID_SELECTION; import static com.android.providers.media.photopicker.PickerDataLayer.QUERY_ROW_ID; import static com.android.providers.media.photopicker.util.CloudProviderUtils.sendInitPhotoPickerDataNotification; @@ -50,14 +51,17 @@ import com.android.providers.media.PickerUriResolver; import com.android.providers.media.photopicker.data.model.Category; import com.android.providers.media.photopicker.data.model.UserId; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.Objects; /** * Provides image and video items from {@link MediaStore} collection to the Photo Picker. */ public class ItemsProvider { private static final String TAG = ItemsProvider.class.getSimpleName(); - private static final boolean DEBUG = false; + private static final boolean DEBUG = true; private static final boolean DEBUG_DUMP_CURSORS = false; private final Context mContext; @@ -109,14 +113,6 @@ public class ItemsProvider { @Nullable String[] mimeTypes, @Nullable UserId userId, @Nullable CancellationSignal cancellationSignal) throws IllegalArgumentException { - if (DEBUG) { - Log.d(TAG, "getAllItems() userId=" + userId + " cat=" + category - + " mimeTypes=" + Arrays.toString(mimeTypes) + " limit=" - + pagingParameters.getPageSize() + " dateTakenBeforeMs=" - + pagingParameters.getDateBeforeMs() + " rowId=" + pagingParameters.getRowId()); - Log.v(TAG, "Thread=" + Thread.currentThread() + "; Stacktrace:", new Throwable()); - } - Trace.beginSection("ItemsProvider.getAllItems"); try { return queryMedia(URI_MEDIA_ALL, pagingParameters, mimeTypes, category, userId, @@ -155,14 +151,6 @@ public class ItemsProvider { @Nullable String[] mimeTypes, @Nullable UserId userId, @Nullable CancellationSignal cancellationSignal) throws IllegalArgumentException { - if (DEBUG) { - Log.d(TAG, "getLocalItems() userId=" + userId + " cat=" + category - + " mimeTypes=" + Arrays.toString(mimeTypes) + " limit=" - + pagingParameters.getPageSize() + " dateTakenBeforeMs=" - + pagingParameters.getDateBeforeMs() + " rowId=" + pagingParameters.getRowId()); - Log.v(TAG, "Thread=" + Thread.currentThread() + "; Stacktrace:", new Throwable()); - } - Trace.beginSection("ItemsProvider.getLocalItems"); try { return queryMedia(URI_MEDIA_LOCAL, pagingParameters, mimeTypes, category, userId, @@ -173,6 +161,26 @@ public class ItemsProvider { } /** + * Gets cursor for items corresponding to the ids passed as an argument. + * + * @param category the category of items to return. + * @param mimeTypes the mime type of item. {@code null} returns all images/videos that are + * scanned by {@link MediaStore}. + * @param userId the {@link UserId} of the user to get items as. + * {@code null} defaults to {@link UserId#CURRENT_USER} + * @param localIdSelection list of ids for which the item objects are required + */ + public Cursor getLocalItemsForSelection(Category category, + @NonNull List<Integer> localIdSelection, + @Nullable String[] mimeTypes, + @Nullable UserId userId, + @Nullable CancellationSignal cancellationSignal) throws IllegalArgumentException { + Objects.requireNonNull(localIdSelection); + return queryMedia(URI_MEDIA_LOCAL, new PaginationParameters(), mimeTypes, category, userId, + localIdSelection, cancellationSignal); + } + + /** * Returns a {@link Cursor} to all non-empty categories in which images/videos are categorised. * This includes: * * A constant list of local categories for on-device images/videos: {@link Category} @@ -189,12 +197,6 @@ public class ItemsProvider { @Nullable public Cursor getAllCategories(@Nullable String[] mimeTypes, @Nullable UserId userId, @Nullable CancellationSignal cancellationSignal) { - if (DEBUG) { - Log.d(TAG, "getAllCategories() userId=" + userId - + " mimeTypes=" + Arrays.toString(mimeTypes)); - Log.v(TAG, "Thread=" + Thread.currentThread() + "; Stacktrace:", new Throwable()); - } - Trace.beginSection("ItemsProvider.getAllCategories"); try { return queryAlbums(URI_ALBUMS_ALL, mimeTypes, userId, cancellationSignal); @@ -218,12 +220,6 @@ public class ItemsProvider { @Nullable public Cursor getLocalCategories(@Nullable String[] mimeTypes, @Nullable UserId userId, @Nullable CancellationSignal cancellationSignal) { - if (DEBUG) { - Log.d(TAG, "getLocalCategories() userId=" + userId - + " mimeTypes=" + Arrays.toString(mimeTypes)); - Log.v(TAG, "Thread=" + Thread.currentThread() + "; Stacktrace:", new Throwable()); - } - Trace.beginSection("ItemsProvider.getLocalCategories"); try { return queryAlbums(URI_ALBUMS_LOCAL, mimeTypes, userId, cancellationSignal); @@ -235,6 +231,15 @@ public class ItemsProvider { @Nullable private Cursor queryMedia(@NonNull Uri uri, PaginationParameters paginationParameters, String[] mimeTypes, @NonNull Category category, @Nullable UserId userId, + @Nullable CancellationSignal cancellationSignal) { + return queryMedia(uri, paginationParameters, mimeTypes, category, userId, null, + cancellationSignal); + } + + @Nullable + private Cursor queryMedia(@NonNull Uri uri, PaginationParameters paginationParameters, + String[] mimeTypes, @NonNull Category category, @Nullable UserId userId, + List<Integer> localIdSelection, @Nullable CancellationSignal cancellationSignal) throws IllegalStateException { if (userId == null) { @@ -242,12 +247,12 @@ public class ItemsProvider { } if (DEBUG) { - Log.d(TAG, "queryMedia() userId=" + userId + " uri=" + uri + " cat=" + category - + " mimeTypes=" + Arrays.toString(mimeTypes) + " limit=" - + paginationParameters.getPageSize() + " date_taken_before_ms = " - + paginationParameters.getDateBeforeMs() + " row_id = " - + paginationParameters.getRowId()); - Log.v(TAG, "Thread=" + Thread.currentThread() + "; Stacktrace:", new Throwable()); + Log.d(TAG, "queryMedia() uri=" + uri + + " cat=" + category + + " mimeTypes=" + Arrays.toString(mimeTypes) + + " limit=" + paginationParameters.getPageSize() + + " date_taken_before_ms = " + paginationParameters.getDateBeforeMs() + + " row_id = " + paginationParameters.getRowId()); } Trace.beginSection("ItemsProvider.queryMedia"); @@ -266,11 +271,16 @@ public class ItemsProvider { } extras.putString(MediaStore.QUERY_ARG_ALBUM_ID, category.getId()); extras.putString(MediaStore.QUERY_ARG_ALBUM_AUTHORITY, category.getAuthority()); + if (paginationParameters.getRowId() >= 0 - && paginationParameters.getDateBeforeMs() >= 0) { + && paginationParameters.getDateBeforeMs() > Long.MIN_VALUE) { extras.putInt(QUERY_ROW_ID, paginationParameters.getRowId()); extras.putLong(QUERY_DATE_TAKEN_BEFORE_MS, paginationParameters.getDateBeforeMs()); } + if (localIdSelection != null) { + extras.putIntegerArrayList(QUERY_LOCAL_ID_SELECTION, + (ArrayList<Integer>) localIdSelection); + } result = client.query(uri, /* projection */ null, extras, /* cancellationSignal */ cancellationSignal); @@ -303,9 +313,8 @@ public class ItemsProvider { } if (DEBUG) { - Log.d(TAG, "queryAlbums() userId=" + userId + " uri=" + uri + Log.d(TAG, "queryAlbums() uri=" + uri + " mimeTypes=" + Arrays.toString(mimeTypes)); - Log.v(TAG, "Thread=" + Thread.currentThread() + "; Stacktrace:", new Throwable()); } Trace.beginSection("ItemsProvider.queryAlbums"); diff --git a/src/com/android/providers/media/photopicker/data/PaginationParameters.java b/src/com/android/providers/media/photopicker/data/PaginationParameters.java index 3df947e49..2d05eb447 100644 --- a/src/com/android/providers/media/photopicker/data/PaginationParameters.java +++ b/src/com/android/providers/media/photopicker/data/PaginationParameters.java @@ -17,7 +17,6 @@ package com.android.providers.media.photopicker.data; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.INT_DEFAULT; -import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.LONG_DEFAULT; /** * Holder for parameters required for pagination of photos and category items grid recyclerView in @@ -25,7 +24,7 @@ import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryF */ public class PaginationParameters { private int mPageSize = INT_DEFAULT; - private long mDateBeforeMs = LONG_DEFAULT; + private long mDateBeforeMs = Long.MIN_VALUE; private int mRowId = INT_DEFAULT; public static final int PAGINATION_PAGE_SIZE_ITEMS = 600; @@ -87,7 +86,7 @@ public class PaginationParameters { * <b>Note: This parameter is only used in the query if the row id is set. Else it is * ignored.</b> */ - public long getDateBeforeMs() { + public Long getDateBeforeMs() { return mDateBeforeMs; } diff --git a/src/com/android/providers/media/photopicker/data/PickerDbFacade.java b/src/com/android/providers/media/photopicker/data/PickerDbFacade.java index 248574bd4..7c0985815 100644 --- a/src/com/android/providers/media/photopicker/data/PickerDbFacade.java +++ b/src/com/android/providers/media/photopicker/data/PickerDbFacade.java @@ -49,11 +49,13 @@ import androidx.annotation.VisibleForTesting; import com.android.providers.media.photopicker.PickerSyncController; import com.android.providers.media.photopicker.data.model.Item; +import com.android.providers.media.photopicker.sync.SyncTrackerRegistry; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; /** * This is a facade that hides the complexities of executing some SQL statements on the picker db. @@ -151,6 +153,7 @@ public class PickerDbFacade { String.format("%s < ? OR (%s = ? AND %s < ?)", KEY_DATE_TAKEN_MS, KEY_DATE_TAKEN_MS, KEY_ID); private static final String WHERE_ALBUM_ID = KEY_ALBUM_ID + " = ?"; + private static final String WHERE_LOCAL_ID_IN = KEY_LOCAL_ID + " IN "; // This where clause returns all rows for media items that are local-only and are marked as // favorite. @@ -396,6 +399,16 @@ public class PickerDbFacade { return null; } + + /** + * Returns the first date taken present in the columns affected by the DB write operation + * when this method is overridden. Otherwise, it returns Long.MIN_VALUE. + */ + public long getFirstDateTakenMillis() { + Log.e(TAG, "Method getFirstDateTakenMillis() is not overridden. " + + "It will always return Long.MIN_VALUE"); + return Long.MIN_VALUE; + } } /** @@ -526,6 +539,8 @@ public class PickerDbFacade { } private static final class RemoveMediaOperation extends DbWriteOperation { + private static final String[] sDateTakenProjection = new String[] {KEY_DATE_TAKEN_MS}; + private long mFirstDateTakenMillis = Long.MIN_VALUE; private RemoveMediaOperation(SQLiteDatabase database, boolean isLocal) { super(database, isLocal); @@ -539,6 +554,10 @@ public class PickerDbFacade { int counter = 0; while (cursor.moveToNext()) { + if (cursor.isFirst()) { + updateFirstDateTakenMillis(cursor, isLocal); + } + // Need to fetch the local_id before delete because for cloud items // we need a db query to fetch the local_id matching the id received from // cursor (cloud_id). @@ -558,6 +577,11 @@ public class PickerDbFacade { return counter; } + @Override + public long getFirstDateTakenMillis() { + return mFirstDateTakenMillis; + } + private void promoteCloudMediaToVisible(@Nullable String localId) { if (localId == null) { return; @@ -594,6 +618,34 @@ public class PickerDbFacade { /* columnIndex */ 0); } } + + private void updateFirstDateTakenMillis(Cursor inputCursor, boolean isLocal) { + final int idIndex = inputCursor + .getColumnIndex(CloudMediaProviderContract.MediaColumns.ID); + if (idIndex < 0) { + Log.e(TAG, "Id is not present in the cursor"); + return; + } + + final String id = inputCursor.getString(idIndex); + if (TextUtils.isEmpty((id))) { + Log.e(TAG, "Input id is empty"); + return; + } + + final SQLiteQueryBuilder qb = isLocal ? QB_MATCH_LOCAL_ONLY : QB_MATCH_CLOUD; + final String[] queryArgs = new String[]{id}; + + try (Cursor outputCursor = qb.query(getDatabase(), sDateTakenProjection, + /* selection */ null, queryArgs, /* groupBy */ null, /* having */ null, + /* orderBy */ null)) { + if (outputCursor.moveToFirst()) { + mFirstDateTakenMillis = outputCursor.getLong(/* columnIndex */ 0); + } else { + Log.e(TAG, "Could not get first date taken millis for media id: " + id); + } + } + } } private static final class ResetMediaOperation extends DbWriteOperation { @@ -641,9 +693,11 @@ public class PickerDbFacade { private final boolean mIsVideo; public boolean mIsLocalOnly; + private List<Integer> mLocalIdSelection; + private QueryFilter(int limit, long dateTakenBeforeMs, long dateTakenAfterMs, long id, String albumId, long sizeBytes, String[] mimeTypes, boolean isFavorite, - boolean isVideo, boolean isLocalOnly) { + boolean isVideo, boolean isLocalOnly, List<Integer> localIdSelection) { this.mLimit = limit; this.mDateTakenBeforeMs = dateTakenBeforeMs; this.mDateTakenAfterMs = dateTakenAfterMs; @@ -654,6 +708,7 @@ public class PickerDbFacade { this.mIsFavorite = isFavorite; this.mIsVideo = isVideo; this.mIsLocalOnly = isLocalOnly; + this.mLocalIdSelection = localIdSelection; } } @@ -665,11 +720,12 @@ public class PickerDbFacade { public static final String[] STRING_ARRAY_DEFAULT = null; public static final boolean BOOLEAN_DEFAULT = false; + public static final List LIST_DEFAULT = null; public static final int LIMIT_DEFAULT = 1000; private final int limit; - private long dateTakenBeforeMs = LONG_DEFAULT; - private long dateTakenAfterMs = LONG_DEFAULT; + private long mDateTakenBeforeMs = Long.MIN_VALUE; + private long mDateTakenAfterMs = Long.MIN_VALUE; private long id = LONG_DEFAULT; private String albumId = STRING_DEFAULT; private long sizeBytes = LONG_DEFAULT; @@ -678,17 +734,19 @@ public class PickerDbFacade { private boolean mIsVideo = BOOLEAN_DEFAULT; private boolean mIsLocalOnly = BOOLEAN_DEFAULT; + private List<Integer> mLocalIdSelection = LIST_DEFAULT; + public QueryFilterBuilder(int limit) { this.limit = limit; } public QueryFilterBuilder setDateTakenBeforeMs(long dateTakenBeforeMs) { - this.dateTakenBeforeMs = dateTakenBeforeMs; + this.mDateTakenBeforeMs = dateTakenBeforeMs; return this; } public QueryFilterBuilder setDateTakenAfterMs(long dateTakenAfterMs) { - this.dateTakenAfterMs = dateTakenAfterMs; + this.mDateTakenAfterMs = dateTakenAfterMs; return this; } @@ -724,6 +782,14 @@ public class PickerDbFacade { } /** + * Sets the local id selection filter. + */ + public QueryFilterBuilder setLocalIdSelection(List<Integer> localIdSelection) { + this.mLocalIdSelection = localIdSelection; + return this; + } + + /** * If {@code isFavorite} is {@code true}, the {@link QueryFilter} returns only * favorited items, however, if it is {@code false}, it returns all items including * favorited and non-favorited items. @@ -753,8 +819,8 @@ public class PickerDbFacade { } public QueryFilter build() { - return new QueryFilter(limit, dateTakenBeforeMs, dateTakenAfterMs, id, albumId, - sizeBytes, mimeTypes, isFavorite, mIsVideo, mIsLocalOnly); + return new QueryFilter(limit, mDateTakenBeforeMs, mDateTakenAfterMs, id, albumId, + sizeBytes, mimeTypes, isFavorite, mIsVideo, mIsLocalOnly, mLocalIdSelection); } } @@ -793,7 +859,7 @@ public class PickerDbFacade { * The result is sorted in reverse chronological order, i.e. newest first, up to a maximum of * {@code limit}. They can also be filtered with {@code query}. */ - public Cursor queryAlbumMediaForUi(QueryFilter query, String authority) { + public Cursor queryAlbumMediaForUi(@NonNull QueryFilter query, @NonNull String authority) { final SQLiteQueryBuilder qb = createAlbumMediaQueryBuilder(isLocal(authority)); final String[] selectionArgs = buildSelectionArgs(qb, query); @@ -841,7 +907,7 @@ public class PickerDbFacade { * Returns empty {@link Cursor} if there are no items matching merged album constraints {@code * query} */ - public Cursor getMergedAlbums(QueryFilter query) { + public Cursor getMergedAlbums(QueryFilter query, String cloudProvider) { final MatrixCursor c = new MatrixCursor(AlbumColumns.ALL_PROJECTION); List<String> mergedAlbums = List.of(ALBUM_ID_FAVORITES, ALBUM_ID_VIDEOS); for (String albumId : mergedAlbums) { @@ -869,7 +935,9 @@ public class PickerDbFacade { } long count = getCursorLong(cursor, CloudMediaProviderContract.AlbumColumns.MEDIA_COUNT); - if (count == 0) { + + // We want to always display empty merged folder in case of cloud picker. + if (count == 0 && (query.mIsLocalOnly || cloudProvider == null)) { continue; } @@ -907,6 +975,9 @@ public class PickerDbFacade { return mLocalProvider.equals(authority); } + /** + * Returns sorted and deduped cloud and local media or album content items from the picker db. + */ private Cursor queryMediaForUi(SQLiteQueryBuilder qb, String[] selectionArgs, int limit, String tableName, String authority) { // Use the <table>.<column> form to order _id to avoid ordering against the projection '_id' @@ -1188,6 +1259,22 @@ public class PickerDbFacade { selectArgs.add(query.mAlbumId); } + if (query.mLocalIdSelection != null && !query.mLocalIdSelection.isEmpty()) { + StringBuilder localIdSelectionPlaceholder = new StringBuilder("("); + for (int itr = 0; itr < query.mLocalIdSelection.size(); itr++) { + localIdSelectionPlaceholder.append("?,"); + } + localIdSelectionPlaceholder.deleteCharAt(localIdSelectionPlaceholder.length() - 1); + localIdSelectionPlaceholder.append(")"); + + // Append the where clause for local id selection to the query builder. + qb.appendWhereStandalone(WHERE_LOCAL_ID_IN + localIdSelectionPlaceholder); + + // Add local ids to the selection args. + selectArgs.addAll(query.mLocalIdSelection.stream().map( + String::valueOf).collect(Collectors.toList())); + } + if (selectArgs.isEmpty()) { return null; } @@ -1361,6 +1448,7 @@ public class PickerDbFacade { final boolean isLocal = isLocal(); final String albumId = getAlbumId(); final SQLiteQueryBuilder qb = createAlbumMediaQueryBuilder(isLocal); + final SQLiteQueryBuilder qbMedia = createMediaQueryBuilder(); int counter = 0; if (cursor.getCount() > PAGE_SIZE) { @@ -1406,11 +1494,46 @@ public class PickerDbFacade { } catch (SQLiteConstraintException e) { Log.v(TAG, "Failed to insert album_media. ContentValues: " + values, e); } + + // Check if a Cloud sync is running, and additionally insert this row to media table + // if true. + maybeInsertFileToMedia(qbMedia, cursor, isLocal); } return counter; } + /** + * Will (possibly) insert this file to the Picker database's media table if there's an + * existing Cloud Sync running. + * + * <p>This is necessary to guarantee it exists in case it is selected by the user. (So that + * the pre-loader can load it to the device before the session is closed.) + * + * @param queryBuilder The media table query builder to use for the insert + * @param cursor The current cursor being processed (this method does not advance the + * cursor). + * @param isLocal Whether this is the local provider sync or not. + */ + private void maybeInsertFileToMedia( + SQLiteQueryBuilder queryBuilder, Cursor cursor, boolean isLocal) { + if (SyncTrackerRegistry.getCloudSyncTracker().pendingSyncFutures().size() > 0) { + ContentValues values = cursorToContentValue(cursor, isLocal); + Log.d( + TAG, + String.format( + "Encountered running Cloud sync during AddAlbumMediaOperation while" + + " processing row. Will additional insert to media table: %s", + values)); + try { + queryBuilder.insert(getDatabase(), values); + } catch (SQLiteConstraintException ignored) { + // If we hit a constraint exception it means this row is already in media, + // so nothing to do here. + } + } + } + private void updateContentValues(ContentValues values, Cursor cursor) { if (cursor.moveToFirst()) { for (int columnIndex = 0; columnIndex < cursor.getColumnCount(); columnIndex++) { diff --git a/src/com/android/providers/media/photopicker/data/Selection.java b/src/com/android/providers/media/photopicker/data/Selection.java index 4894977ea..7176aaded 100644 --- a/src/com/android/providers/media/photopicker/data/Selection.java +++ b/src/com/android/providers/media/photopicker/data/Selection.java @@ -27,6 +27,7 @@ import androidx.lifecycle.MutableLiveData; import com.android.providers.media.photopicker.data.model.Item; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -36,6 +37,16 @@ import java.util.Map; * A class that tracks Selection */ public class Selection { + /** + * Contains positions of checked Item at UI. {@link #mCheckedItemIndexes} may have more number + * of indexes , from the number of items present in {@link #mSelectedItems}. The index in + * {@link #mCheckedItemIndexes} is a potential index that needs to be rechecked in + * notifyItemChanged() at the time of deselecting the unavailable item at UI when user is + * offline and tries adding unavailable non cached items. the item corresponding to the index in + * {@link #mCheckedItemIndexes} may no longer be selected. + */ + private final Map<Item, Integer> mCheckedItemIndexes = new HashMap<>(); + // The list of selected items. private Map<Uri, Item> mSelectedItems = new HashMap<>(); private MutableLiveData<Integer> mSelectedItemSize = new MutableLiveData<>(); @@ -55,6 +66,13 @@ public class Selection { } /** + * @return Indexes - A {@link List} of checked {@link Item} positions. + */ + public Collection<Integer> getCheckedItemsIndexes() { + return mCheckedItemIndexes.values(); + } + + /** * @return {@link LiveData} of count of selected items in {@link #mSelectedItems} */ public LiveData<Integer> getSelectedItemCount() { @@ -74,6 +92,13 @@ public class Selection { } /** + * Add the checked {@code item} index into {@link #mCheckedItemIndexes}. + */ + public void addCheckedItemIndex(Item item, Integer index) { + mCheckedItemIndexes.put(item, index); + } + + /** * Clears {@link #mSelectedItems} and sets the selected item as given {@code item} */ public void setSelectedItem(Item item) { @@ -84,7 +109,7 @@ public class Selection { } /** - * Remove the {@code item} from the selected item list {@link #mSelectedItems}. + * Remove the {@code item} from the selected item list {@link #mSelectedItems} * * @param item the item to be removed from the selected item list */ @@ -95,15 +120,32 @@ public class Selection { } /** - * Clear all selected items + * Remove the {@code item} index from the checked item index list {@link #mCheckedItemIndexes}. + * + * @param item the item to be removed from the selected item list + */ + public void removeCheckedItemIndex(Item item) { + mCheckedItemIndexes.remove(item); + } + + /** + * Clear all selected items and checked positions */ public void clearSelectedItems() { mSelectedItems.clear(); + mCheckedItemIndexes.clear(); mSelectedItemSize.postValue(mSelectedItems.size()); updateSelectionAllowed(); } /** + * Clear all checked items + */ + public void clearCheckedItemList() { + mCheckedItemIndexes.clear(); + } + + /** * @return {@code true} if give {@code item} is present in selected items * {@link #mSelectedItems}, {@code false} otherwise */ diff --git a/src/com/android/providers/media/photopicker/data/model/Category.java b/src/com/android/providers/media/photopicker/data/model/Category.java index 7ccda79f7..487a39c26 100644 --- a/src/com/android/providers/media/photopicker/data/model/Category.java +++ b/src/com/android/providers/media/photopicker/data/model/Category.java @@ -40,6 +40,7 @@ import androidx.annotation.VisibleForTesting; import com.android.providers.media.R; import com.android.providers.media.photopicker.data.ItemsProvider; +import java.util.List; import java.util.Locale; /** @@ -49,6 +50,8 @@ public class Category { public static final String TAG = "PhotoPicker"; public static final Category DEFAULT = new Category(); public static final Category EMPTY_VIEW = new Category("EMPTY_VIEW"); + private static final List<String> TRANSLATABLE_CATEGORIES = List.of(ALBUM_ID_VIDEOS, + ALBUM_ID_CAMERA, ALBUM_ID_SCREENSHOTS, ALBUM_ID_DOWNLOADS, ALBUM_ID_FAVORITES); private final String mId; private final String mAuthority; @@ -91,7 +94,7 @@ public class Category { } public String getDisplayName(Context context) { - if (mIsLocal) { + if (TRANSLATABLE_CATEGORIES.contains(mId)) { return getLocalizedDisplayName(context, mId); } return mDisplayName; @@ -163,7 +166,7 @@ public class Category { return new Category(getCursorString(cursor, AlbumColumns.ID), authority, getCursorString(cursor, AlbumColumns.DISPLAY_NAME), - coverUri, + getCursorString(cursor, AlbumColumns.MEDIA_COVER_ID) != null ? coverUri : null, getCursorInt(cursor, AlbumColumns.MEDIA_COUNT), isLocal); } diff --git a/src/com/android/providers/media/photopicker/data/model/Item.java b/src/com/android/providers/media/photopicker/data/model/Item.java index e618386f2..11dbc643d 100644 --- a/src/com/android/providers/media/photopicker/data/model/Item.java +++ b/src/com/android/providers/media/photopicker/data/model/Item.java @@ -41,6 +41,8 @@ import com.android.providers.media.photopicker.data.ItemsProvider; import com.android.providers.media.photopicker.util.DateTimeUtils; import com.android.providers.media.util.MimeUtils; +import java.util.Objects; + /** * Base class for representing a single media item (a picture, a video, etc.) in the PhotoPicker. */ @@ -225,4 +227,17 @@ public class Item { public boolean isLocal() { return LOCAL_PICKER_PROVIDER_AUTHORITY.equals(mUri.getAuthority()); } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || !(obj instanceof Item)) return false; + + Item other = (Item) obj; + return mUri.equals(other.mUri); + } + + @Override public int hashCode() { + return Objects.hash(mUri); + } }
\ No newline at end of file diff --git a/src/com/android/providers/media/photopicker/sync/ImmediateAlbumSyncWorker.java b/src/com/android/providers/media/photopicker/sync/ImmediateAlbumSyncWorker.java index dea21f3fd..bc896d59d 100644 --- a/src/com/android/providers/media/photopicker/sync/ImmediateAlbumSyncWorker.java +++ b/src/com/android/providers/media/photopicker/sync/ImmediateAlbumSyncWorker.java @@ -29,11 +29,13 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.work.ForegroundInfo; import androidx.work.ListenableWorker; import androidx.work.Worker; import androidx.work.WorkerParameters; import com.android.providers.media.photopicker.PickerSyncController; +import com.android.providers.media.photopicker.util.exceptions.RequestObsoleteException; /** * This is a {@link Worker} class responsible for syncing album media with the correct sync source. @@ -41,6 +43,7 @@ import com.android.providers.media.photopicker.PickerSyncController; public class ImmediateAlbumSyncWorker extends Worker { private static final String TAG = "IASyncWorker"; private static final int INVALID_SYNC_SOURCE = -1; + private final Context mContext; /** * Creates an instance of the {@link Worker}. @@ -52,6 +55,7 @@ public class ImmediateAlbumSyncWorker extends Worker { @NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); + mContext = context; } @NonNull @@ -71,6 +75,7 @@ public class ImmediateAlbumSyncWorker extends Worker { // No need to instantiate a work request tracker for immediate syncs in the worker. // For immediate syncs, the work request tracker is initiated before enqueueing the // request in WorkManager. + checkIsWorkerStopped(); if (syncSource == SYNC_LOCAL_ONLY) { PickerSyncController.getInstanceOrThrow().syncAlbumMediaFromLocalProvider(albumId); } else { @@ -81,7 +86,7 @@ public class ImmediateAlbumSyncWorker extends Worker { "Completed picker immediate album sync from sync source: %s album id: %s", syncSource, albumId)); return ListenableWorker.Result.success(); - } catch (IllegalArgumentException | IllegalStateException e) { + } catch (IllegalArgumentException | IllegalStateException | RequestObsoleteException e) { Log.e(TAG, String.format("Could not complete picker immediate album sync from " + "sync source: %s album id: %s", syncSource, albumId), e); @@ -105,4 +110,25 @@ public class ImmediateAlbumSyncWorker extends Worker { throw new IllegalArgumentException("Invalid album id " + albumId); } } + + private void checkIsWorkerStopped() throws RequestObsoleteException { + if (isStopped()) { + throw new RequestObsoleteException("Work is stopped " + getId()); + } + } + + @Override + @NonNull + public ForegroundInfo getForegroundInfo() { + return PickerSyncNotificationHelper.getForegroundInfo(mContext); + } + + @Override + public void onStopped() { + Log.w(TAG, "Worker is stopped. Clearing all pending futures. It's possible that the sync " + + "will continue to run if it has started already."); + final int syncSource = getInputData() + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, /* defaultValue */ SYNC_LOCAL_ONLY); + markAlbumMediaSyncAsComplete(syncSource, getId()); + } } diff --git a/src/com/android/providers/media/photopicker/sync/ImmediateSyncWorker.java b/src/com/android/providers/media/photopicker/sync/ImmediateSyncWorker.java index 9ea5a9afc..f4ad8d4ba 100644 --- a/src/com/android/providers/media/photopicker/sync/ImmediateSyncWorker.java +++ b/src/com/android/providers/media/photopicker/sync/ImmediateSyncWorker.java @@ -29,17 +29,20 @@ import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; +import androidx.work.ForegroundInfo; import androidx.work.ListenableWorker; import androidx.work.Worker; import androidx.work.WorkerParameters; import com.android.providers.media.photopicker.PickerSyncController; +import com.android.providers.media.photopicker.util.exceptions.RequestObsoleteException; /** * This is a {@link Worker} class responsible for syncing with the correct sync source. */ public class ImmediateSyncWorker extends Worker { private static final String TAG = "ISyncWorker"; + private final Context mContext; /** * Creates an instance of the {@link Worker}. @@ -49,13 +52,14 @@ public class ImmediateSyncWorker extends Worker { */ public ImmediateSyncWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); + mContext = context; } @NonNull @Override public ListenableWorker.Result doWork() { final int syncSource = getInputData() - .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, /* defaultValue */ SYNC_LOCAL_AND_CLOUD); + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, /* defaultValue */ SYNC_LOCAL_ONLY); Log.i(TAG, String.format( "Starting immediate picker sync from sync source: %s", syncSource)); @@ -65,17 +69,19 @@ public class ImmediateSyncWorker extends Worker { // For immediate syncs, the work request tracker is initiated before enqueueing the // request in WorkManager. if (syncSource == SYNC_LOCAL_AND_CLOUD || syncSource == SYNC_LOCAL_ONLY) { + checkIsWorkerStopped(); PickerSyncController.getInstanceOrThrow().syncAllMediaFromLocalProvider(); getLocalSyncTracker().markSyncCompleted(getId()); Log.i(TAG, "Completed immediate picker sync from local provider."); } if (syncSource == SYNC_LOCAL_AND_CLOUD || syncSource == SYNC_CLOUD_ONLY) { + checkIsWorkerStopped(); PickerSyncController.getInstanceOrThrow().syncAllMediaFromCloudProvider(); getCloudSyncTracker().markSyncCompleted(getId()); Log.i(TAG, "Completed immediate picker sync from cloud provider."); } return ListenableWorker.Result.success(); - } catch (IllegalStateException e) { + } catch (IllegalStateException | RequestObsoleteException e) { Log.i(TAG, String.format( "Could not complete immediate sync from sync source: %s", syncSource), e); @@ -84,4 +90,25 @@ public class ImmediateSyncWorker extends Worker { return ListenableWorker.Result.failure(); } } + + private void checkIsWorkerStopped() throws RequestObsoleteException { + if (isStopped()) { + throw new RequestObsoleteException("Work is stopped " + getId()); + } + } + + @Override + @NonNull + public ForegroundInfo getForegroundInfo() { + return PickerSyncNotificationHelper.getForegroundInfo(mContext); + } + + @Override + public void onStopped() { + Log.w(TAG, "Worker is stopped. Clearing all pending futures. It's possible that the sync " + + "still finishes running if it has started already."); + final int syncSource = getInputData() + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, /* defaultValue */ SYNC_LOCAL_AND_CLOUD); + markSyncAsComplete(syncSource, getId()); + } } diff --git a/src/com/android/providers/media/photopicker/sync/MediaResetWorker.java b/src/com/android/providers/media/photopicker/sync/MediaResetWorker.java new file mode 100644 index 000000000..47c745583 --- /dev/null +++ b/src/com/android/providers/media/photopicker/sync/MediaResetWorker.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.media.photopicker.sync; + +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_CLOUD_ONLY; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_LOCAL_ONLY; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_RESET_ALBUM; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_RESET_MEDIA; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_ALBUM_ID; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_AUTHORITY; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_RESET_TYPE; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_SYNC_SOURCE; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_TAG_IS_PERIODIC; +import static com.android.providers.media.photopicker.sync.SyncTrackerRegistry.markAlbumMediaSyncAsComplete; +import static com.android.providers.media.photopicker.sync.SyncTrackerRegistry.trackNewAlbumMediaSyncRequests; + +import android.content.Context; +import android.database.sqlite.SQLiteException; +import android.os.Trace; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.work.ForegroundInfo; +import androidx.work.ListenableWorker; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +import com.android.providers.media.photopicker.PickerSyncController; +import com.android.providers.media.photopicker.data.PickerDbFacade; +import com.android.providers.media.photopicker.sync.PickerSyncManager.SyncResetType; + +/** + * This is a {@link Worker} class responsible for handling table reset operations in the picker + * database. + */ +public class MediaResetWorker extends Worker { + + private static final String TAG = "MediaResetWorker"; + private static final int UNDEFINED_RESET_TYPE = -1; + + @Nullable private final String mAlbumId; + @NonNull private final Context mContext; + @NonNull private final int mResetType; + @NonNull private final int mSyncSource; + + @Nullable private String mAuthority; + + public MediaResetWorker(@NonNull Context context, @NonNull WorkerParameters workerParameters) { + super(context, workerParameters); + mContext = context; + + mAuthority = getInputData().getString(SYNC_WORKER_INPUT_AUTHORITY); + mAlbumId = getInputData().getString(SYNC_WORKER_INPUT_ALBUM_ID); + mResetType = getInputData().getInt(SYNC_WORKER_INPUT_RESET_TYPE, UNDEFINED_RESET_TYPE); + mSyncSource = getInputData().getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1); + } + + @Override + public ListenableWorker.Result doWork() { + Log.i( + TAG, + String.format( + "MediaReset has been requested. Authority: %s AlbumId: %s", + mAuthority, mAlbumId)); + + PickerSyncController controller; + PickerDbFacade dBFacade; + try { + controller = PickerSyncController.getInstanceOrThrow(); + dBFacade = new PickerDbFacade(mContext); + } catch (IllegalStateException ex) { + Log.e(TAG, "Unable to obtain PickerSyncController", ex); + return ListenableWorker.Result.failure(); + } catch (SQLiteException ex) { + Log.e(TAG, "Unable to get writeable database", ex); + return ListenableWorker.Result.failure(); + } + + if (getTags().contains(SYNC_WORKER_TAG_IS_PERIODIC)) { + // If this worker is being run as part of periodic work, it needs to register + // its own sync with the sync tracker. + trackNewAlbumMediaSyncRequests(mSyncSource, getId()); + + // Since this is a periodic worker, we'll use the cloud authority, if it exists. + // Using the cloud authority will reset files for all providers. If the local + // authority is used, it will limit the query to only files with a local_id, but + // the cloud authority does not have such a limitation. + // (This is not intuitive, it's just how it works.) + mAuthority = controller.getCloudProvider(); + if (mAuthority == null) { + mAuthority = controller.getLocalProvider(); + } + // If the authority is still null, end the operation. + if (mAuthority == null) { + Log.e(TAG, "Unable to set authority for periodic worker"); + return ListenableWorker.Result.failure(); + } + } + + try { + + if (mSyncSource == SYNC_LOCAL_ONLY) { + return start(dBFacade); + } else { + // SyncSource is either CLOUD_ONLY or LOCAL_AND_CLOUD, either way we need the + // cloud lock. + final Object cloudAlbumSyncLock = controller.getCloudAlbumSyncLock(); + synchronized (cloudAlbumSyncLock) { + return start(dBFacade); + } + } + } finally { + markAlbumMediaSyncAsComplete(mSyncSource, getId()); + } + } + + private ListenableWorker.Result start(@NonNull PickerDbFacade dbFacade) { + + Trace.beginSection("MediaResetWorker:BeginOperation"); + + int deleteCount = 0; + try (PickerDbFacade.DbWriteOperation operation = + beginResetOperation(dbFacade, mResetType)) { + + deleteCount = operation.execute(/* cursor= */ null); + + // Just ensure the worker hasn't been stopped before allowing the commit. + if (isStopped()) { + Log.i(TAG, "Worker was stopped before operation was completed"); + return ListenableWorker.Result.failure(); + } + operation.setSuccess(); + + } catch (UnsupportedOperationException | IllegalStateException ex) { + Log.e(TAG, "Operation failed.", ex); + return ListenableWorker.Result.failure(); + } finally { + Trace.endSection(); + } + + Log.i(TAG, String.format("Reset operation complete. Deleted rows: %d", deleteCount)); + return ListenableWorker.Result.success(); + } + + private PickerDbFacade.DbWriteOperation beginResetOperation( + @NonNull PickerDbFacade dbFacade, @NonNull @SyncResetType int resetType) { + + switch (resetType) { + case SYNC_RESET_ALBUM: + if (mAuthority == null) { + throw new IllegalStateException( + String.format( + "Failed to begin SYNC_RESET_ALBUM. Unknown provider authority:" + + " %s", + mAuthority)); + } + + if (mSyncSource == SYNC_CLOUD_ONLY && mAlbumId == null) { + Log.w( + TAG, + "Sync Source is set to SYNC_CLOUD_ONLY with no albumId, but the reset" + + " operation will still remove cloud+local files."); + } + return dbFacade.beginResetAlbumMediaOperation(mAuthority, mAlbumId); + case SYNC_RESET_MEDIA: + default: + throw new UnsupportedOperationException( + String.format( + "Requested Reset operation not (yet) supported. ResetType: %d", + resetType)); + } + } + + @Override + @NonNull + public ForegroundInfo getForegroundInfo() { + return PickerSyncNotificationHelper.getForegroundInfo(mContext); + } + + @Override + public void onStopped() { + Log.w( + TAG, + "Worker is stopped. Clearing all pending futures. It's possible that the worker " + + "still finishes running if it has started already."); + markAlbumMediaSyncAsComplete(mSyncSource, getId()); + } +} diff --git a/src/com/android/providers/media/photopicker/sync/PickerSyncManager.java b/src/com/android/providers/media/photopicker/sync/PickerSyncManager.java index ab4cb2c02..ab94d2072 100644 --- a/src/com/android/providers/media/photopicker/sync/PickerSyncManager.java +++ b/src/com/android/providers/media/photopicker/sync/PickerSyncManager.java @@ -21,6 +21,9 @@ import static com.android.providers.media.photopicker.sync.SyncTrackerRegistry.m import static com.android.providers.media.photopicker.sync.SyncTrackerRegistry.trackNewAlbumMediaSyncRequests; import static com.android.providers.media.photopicker.sync.SyncTrackerRegistry.trackNewSyncRequests; +import static java.util.Objects.requireNonNull; + +import android.content.Context; import android.util.Log; import androidx.annotation.IntDef; @@ -33,20 +36,25 @@ import androidx.work.OneTimeWorkRequest; import androidx.work.Operation; import androidx.work.OutOfQuotaPolicy; import androidx.work.PeriodicWorkRequest; +import androidx.work.WorkInfo; import androidx.work.WorkManager; +import androidx.work.Worker; +import com.android.modules.utils.BackgroundThread; import com.android.providers.media.ConfigStore; +import com.android.providers.media.photopicker.PickerSyncController; + +import com.google.common.util.concurrent.ListenableFuture; import org.jetbrains.annotations.NotNull; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; - /** * This class manages all the triggers for Picker syncs. * <p></p> @@ -68,21 +76,102 @@ public class PickerSyncManager { @IntDef(value = { SYNC_LOCAL_ONLY, SYNC_CLOUD_ONLY, SYNC_LOCAL_AND_CLOUD }) @Retention(RetentionPolicy.SOURCE) public @interface SyncSource {} + + public static final int SYNC_RESET_MEDIA = 1; + public static final int SYNC_RESET_ALBUM = 2; + + @IntDef(value = {SYNC_RESET_MEDIA, SYNC_RESET_ALBUM}) + @Retention(RetentionPolicy.SOURCE) + public @interface SyncResetType {} + + static final String SYNC_WORKER_INPUT_AUTHORITY = "INPUT_AUTHORITY"; static final String SYNC_WORKER_INPUT_SYNC_SOURCE = "INPUT_SYNC_TYPE"; + static final String SYNC_WORKER_INPUT_RESET_TYPE = "INPUT_RESET_TYPE"; static final String SYNC_WORKER_INPUT_ALBUM_ID = "INPUT_ALBUM_ID"; + static final String SYNC_WORKER_TAG_IS_PERIODIC = "PERIODIC"; private static final int SYNC_MEDIA_PERIODIC_WORK_INTERVAL = 4; // Time unit is hours. - private static final String SYNC_MEDIA_PERIODIC_SYNC_PREFIX = "SYNC_MEDIA_PERIODIC_"; - private static final String SYNC_MEDIA_PROACTIVE_WORK_PREFIX = "SYNC_MEDIA_PROACTIVE_"; - private static final String SYNC_ALL_WORK_SUFFIX = "ALL"; + private static final int RESET_ALBUM_MEDIA_PERIODIC_WORK_INTERVAL = 12; // Time unit is hours. + + private static final String PERIODIC_SYNC_WORK_NAME; + private static final String PROACTIVE_SYNC_WORK_NAME; + public static final String IMMEDIATE_LOCAL_SYNC_WORK_NAME; + private static final String IMMEDIATE_CLOUD_SYNC_WORK_NAME; + public static final String IMMEDIATE_ALBUM_SYNC_WORK_NAME; + private static final String PERIODIC_ALBUM_RESET_WORK_NAME; + + static { + final String syncPeriodicPrefix = "SYNC_MEDIA_PERIODIC_"; + final String syncProactivePrefix = "SYNC_MEDIA_PROACTIVE_"; + final String syncImmediatePrefix = "SYNC_MEDIA_IMMEDIATE_"; + final String syncAllSuffix = "ALL"; + final String syncLocalSuffix = "LOCAL"; + final String syncCloudSuffix = "CLOUD"; + + PERIODIC_ALBUM_RESET_WORK_NAME = "RESET_ALBUM_MEDIA_PERIODIC"; + PERIODIC_SYNC_WORK_NAME = syncPeriodicPrefix + syncAllSuffix; + PROACTIVE_SYNC_WORK_NAME = syncProactivePrefix + syncAllSuffix; + IMMEDIATE_LOCAL_SYNC_WORK_NAME = syncImmediatePrefix + syncLocalSuffix; + IMMEDIATE_CLOUD_SYNC_WORK_NAME = syncImmediatePrefix + syncCloudSuffix; + IMMEDIATE_ALBUM_SYNC_WORK_NAME = "SYNC_ALBUM_MEDIA_IMMEDIATE"; + } + private final WorkManager mWorkManager; + private final ConfigStore mConfigStore; + private final Context mContext; public PickerSyncManager(@NonNull WorkManager workManager, + @NonNull Context context, @NonNull ConfigStore configStore, - boolean schedulePeriodicSyncs) { - mWorkManager = workManager; + boolean shouldSchedulePeriodicSyncs) { + mWorkManager = requireNonNull(workManager); + mConfigStore = requireNonNull(configStore); + mContext = requireNonNull(context); + + if (shouldSchedulePeriodicSyncs) { + setUpPeriodicWork(); + } + + // Subscribe to device config changes so we can enable periodic workers if Cloud + // Photopicker is enabled. + mConfigStore.addOnChangeListener(BackgroundThread.getExecutor(), this::setUpPeriodicWork); + } + + /** + * Will register new unique {@link Worker} for periodic sync and picker database maintenance if + * the cloud photopicker experiment is currently enabled. + */ + private void setUpPeriodicWork() { + + if (mConfigStore.isCloudMediaInPhotoPickerEnabled()) { + PickerSyncNotificationHelper.createNotificationChannel(mContext); - if (schedulePeriodicSyncs && configStore.isCloudMediaInPhotoPickerEnabled()) { schedulePeriodicSyncs(); + schedulePeriodicAlbumReset(); + } else { + // Disable any scheduled ongoing work if the feature is disabled. + mWorkManager.cancelUniqueWork(PERIODIC_SYNC_WORK_NAME); + mWorkManager.cancelUniqueWork(PERIODIC_ALBUM_RESET_WORK_NAME); + } + } + + /** + * Returns true if the given unique work is pending. In case the unique work is complete or + * there was an error in getting the work state, it returns false. + */ + public boolean isUniqueWorkPending(String uniqueWorkName) { + ListenableFuture<List<WorkInfo>> future = + mWorkManager.getWorkInfosForUniqueWork(uniqueWorkName); + try { + List<WorkInfo> workInfos = future.get(); + for (WorkInfo workInfo : workInfos) { + if (!workInfo.getState().isFinished()) { + return true; + } + } + return false; + } catch (InterruptedException | ExecutionException e) { + Log.e(TAG, "Error occurred in fetching work info - ignore pending work"); + return false; } } @@ -96,9 +185,9 @@ public class PickerSyncManager { try { // Note that the first execution of periodic work happens immediately or as soon as the // given Constraints are met. - Operation enqueueOperation = mWorkManager + final Operation enqueueOperation = mWorkManager .enqueueUniquePeriodicWork( - SYNC_MEDIA_PERIODIC_SYNC_PREFIX + SYNC_ALL_WORK_SUFFIX, + PERIODIC_SYNC_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, periodicSyncRequest ); @@ -110,6 +199,35 @@ public class PickerSyncManager { } } + private void schedulePeriodicAlbumReset() { + Log.i(TAG, "Scheduling periodic picker album data resets"); + + final Data inputData = + new Data( + Map.of( + SYNC_WORKER_INPUT_SYNC_SOURCE, + SYNC_LOCAL_AND_CLOUD, + SYNC_WORKER_INPUT_RESET_TYPE, + SYNC_RESET_ALBUM)); + final PeriodicWorkRequest periodicAlbumResetRequest = + getPeriodicAlbumResetRequest(inputData); + + try { + // Note that the first execution of periodic work happens immediately or as soon + // as the given Constraints are met. + Operation enqueueOperation = + mWorkManager.enqueueUniquePeriodicWork( + PERIODIC_ALBUM_RESET_WORK_NAME, + ExistingPeriodicWorkPolicy.KEEP, + periodicAlbumResetRequest); + + // Check that the request has been successfully enqueued. + enqueueOperation.getResult().get(); + } catch (InterruptedException | ExecutionException e) { + Log.e(TAG, "Could not enqueue periodic picker album resets request", e); + } + } + /** * Use this method for proactive syncs. The sync might take a while to start. Some device state * conditions may apply before the sync can start like battery level etc. @@ -119,16 +237,10 @@ public class PickerSyncManager { new Data(Map.of(SYNC_WORKER_INPUT_SYNC_SOURCE, SYNC_LOCAL_AND_CLOUD)); final OneTimeWorkRequest syncRequest = getOneTimeProactiveSyncRequest(inputData); - final String workName = SYNC_MEDIA_PROACTIVE_WORK_PREFIX + SYNC_ALL_WORK_SUFFIX; - try { - Operation enqueueOperation = mWorkManager - .enqueueUniqueWork(workName, ExistingWorkPolicy.KEEP, syncRequest); - - // Check that the request has been successfully enqueued. - enqueueOperation.getResult().get(); - } catch (InterruptedException | ExecutionException e) { - Log.e(TAG, "Could not enqueue proactive picker sync request", e); - } + // Don't wait for the sync operation to enqueue so that Picker sync enqueue requests in + // order to avoid adding latency to critical MP code paths. + mWorkManager.enqueueUniqueWork(PROACTIVE_SYNC_WORK_NAME, ExistingWorkPolicy.KEEP, + syncRequest); } /** @@ -139,27 +251,27 @@ public class PickerSyncManager { * local and cloud provider. */ public void syncMediaImmediately(boolean shouldSyncLocalOnlyData) { - if (shouldSyncLocalOnlyData) { - syncMediaImmediately(PickerSyncManager.SYNC_LOCAL_ONLY); - } else { - syncMediaImmediately(PickerSyncManager.SYNC_LOCAL_AND_CLOUD); + syncMediaImmediately(PickerSyncManager.SYNC_LOCAL_ONLY, IMMEDIATE_LOCAL_SYNC_WORK_NAME); + if (!shouldSyncLocalOnlyData) { + syncMediaImmediately(PickerSyncManager.SYNC_CLOUD_ONLY, IMMEDIATE_CLOUD_SYNC_WORK_NAME); } } /** * Use this method for reactive syncs with either, local and cloud providers, or both. */ - private void syncMediaImmediately(@SyncSource int syncSource) { + private void syncMediaImmediately(@SyncSource int syncSource, @NonNull String workName) { final Data inputData = new Data(Map.of(SYNC_WORKER_INPUT_SYNC_SOURCE, syncSource)); - final OneTimeWorkRequest syncRequest = getImmediateSyncRequest(inputData); + final OneTimeWorkRequest syncRequest = + buildOneTimeWorkerRequest(ImmediateSyncWorker.class, inputData); // Track the new sync request(s) trackNewSyncRequests(syncSource, syncRequest.getId()); - // Enqueue local sync then cloud sync requests + // Enqueue local or cloud sync request try { final Operation enqueueOperation = mWorkManager - .enqueue(Collections.singletonList(syncRequest)); + .enqueueUniqueWork(workName, ExistingWorkPolicy.APPEND_OR_REPLACE, syncRequest); // Check that the request has been successfully enqueued. enqueueOperation.getResult().get(); @@ -173,69 +285,92 @@ public class PickerSyncManager { * Use this method for reactive syncs which are user action triggered. * * @param albumId is the id of the album that needs to be synced. - * @param isLocal is true when the authority when the sync type is local. - * For cloud syncs, this is false. + * @param authority The authority of the album media. */ public void syncAlbumMediaForProviderImmediately( - @NonNull String albumId, - boolean isLocal) { - syncAlbumMediaForProviderImmediately(albumId, getSyncSource(isLocal)); + @NonNull String albumId, @NonNull String authority) { + boolean isLocal = PickerSyncController.LOCAL_PICKER_PROVIDER_AUTHORITY.equals(authority); + syncAlbumMediaForProviderImmediately(albumId, getSyncSource(isLocal), authority); } /** * Use this method for reactive syncs which are user action triggered. * * @param albumId is the id of the album that needs to be synced. - * @param syncSource indicates if the sync is required with local provider or cloud provider - * or both. + * @param syncSource indicates if the sync is required with local provider or cloud provider or + * both. */ private void syncAlbumMediaForProviderImmediately( - @NonNull String albumId, - @SyncSource int syncSource) { - final Data inputData = new Data(Map.of( - SYNC_WORKER_INPUT_SYNC_SOURCE, syncSource, - SYNC_WORKER_INPUT_ALBUM_ID, albumId)); - final OneTimeWorkRequest syncRequest = getImmediateAlbumSyncRequest(inputData); + @NonNull String albumId, @SyncSource int syncSource, String authority) { + final Data inputData = + new Data( + Map.of( + SYNC_WORKER_INPUT_AUTHORITY, authority, + SYNC_WORKER_INPUT_SYNC_SOURCE, syncSource, + SYNC_WORKER_INPUT_RESET_TYPE, SYNC_RESET_ALBUM, + SYNC_WORKER_INPUT_ALBUM_ID, albumId)); + final OneTimeWorkRequest resetRequest = + buildOneTimeWorkerRequest(MediaResetWorker.class, inputData); + final OneTimeWorkRequest syncRequest = + buildOneTimeWorkerRequest(ImmediateAlbumSyncWorker.class, inputData); // Track the new sync request(s) + trackNewAlbumMediaSyncRequests(syncSource, resetRequest.getId()); trackNewAlbumMediaSyncRequests(syncSource, syncRequest.getId()); - - // Enqueue local sync then cloud sync requests + // Enqueue local or cloud sync requests try { - final Operation enqueueOperation = mWorkManager - .enqueue(Collections.singletonList(syncRequest)); + final Operation enqueueOperation = + mWorkManager + .beginUniqueWork( + IMMEDIATE_ALBUM_SYNC_WORK_NAME, + ExistingWorkPolicy.APPEND_OR_REPLACE, + resetRequest) + .then(syncRequest).enqueue(); // Check that the request has been successfully enqueued. enqueueOperation.getResult().get(); } catch (Exception e) { Log.e(TAG, "Could not enqueue expedited picker sync request", e); + markAlbumMediaSyncAsComplete(syncSource, resetRequest.getId()); markAlbumMediaSyncAsComplete(syncSource, syncRequest.getId()); } } @NotNull - private OneTimeWorkRequest getImmediateSyncRequest(@NotNull Data inputData) { - return new OneTimeWorkRequest.Builder(ImmediateSyncWorker.class) + private OneTimeWorkRequest buildOneTimeWorkerRequest( + @NotNull Class<? extends Worker> workerClass, @NonNull Data inputData) { + return new OneTimeWorkRequest.Builder(workerClass) .setInputData(inputData) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build(); } @NotNull - private OneTimeWorkRequest getImmediateAlbumSyncRequest(@NotNull Data inputData) { - return new OneTimeWorkRequest.Builder(ImmediateAlbumSyncWorker.class) + private PeriodicWorkRequest getPeriodicProactiveSyncRequest(@NotNull Data inputData) { + return new PeriodicWorkRequest.Builder( + ProactiveSyncWorker.class, SYNC_MEDIA_PERIODIC_WORK_INTERVAL, TimeUnit.HOURS) .setInputData(inputData) - .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) + .setConstraints(getProactiveSyncConstraints()) .build(); } @NotNull - private PeriodicWorkRequest getPeriodicProactiveSyncRequest(@NotNull Data inputData) { + private PeriodicWorkRequest getPeriodicAlbumResetRequest(@NotNull Data inputData) { + + Constraints constraints = + new Constraints.Builder() + .setRequiresBatteryNotLow(true) + .setRequiresDeviceIdle(true) + .build(); + return new PeriodicWorkRequest.Builder( - ProactiveSyncWorker.class, SYNC_MEDIA_PERIODIC_WORK_INTERVAL, TimeUnit.HOURS) + MediaResetWorker.class, + RESET_ALBUM_MEDIA_PERIODIC_WORK_INTERVAL, + TimeUnit.HOURS) .setInputData(inputData) - .setConstraints(getProactiveSyncConstraints()) + .setConstraints(constraints) + .addTag(SYNC_WORKER_TAG_IS_PERIODIC) .build(); } @@ -249,7 +384,6 @@ public class PickerSyncManager { @NotNull private static Constraints getProactiveSyncConstraints() { - // TODO these constraints are not finalised. return new Constraints.Builder() .setRequiresBatteryNotLow(true) .build(); diff --git a/src/com/android/providers/media/photopicker/sync/PickerSyncNotificationHelper.java b/src/com/android/providers/media/photopicker/sync/PickerSyncNotificationHelper.java new file mode 100644 index 000000000..e30f2eb49 --- /dev/null +++ b/src/com/android/providers/media/photopicker/sync/PickerSyncNotificationHelper.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.media.photopicker.sync; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.content.res.Resources; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; +import androidx.work.ForegroundInfo; + +import com.android.modules.utils.build.SdkLevel; +import com.android.providers.media.R; + +/** + * Helper functions for Picker sync notifications. + */ +public class PickerSyncNotificationHelper { + private static final String TAG = "SyncNotifHelper"; + private static final String NOTIFICATION_CHANNEL_ID = "PhotoPickerSyncChannel"; + private static final int NOTIFICATION_ID = 0; + private static final int NOTIFICATION_TIMEOUT_MILLIS = 1000; + + + /** + * Created notification channel for Picker Sync notifications. + * Recreating an existing notification channel with its original values performs no operation, + * so it's safe to call this code when starting an app. + */ + public static void createNotificationChannel(@NonNull Context context) { + final String contentTitle = context.getResources() + .getString(R.string.picker_sync_notification_channel); + + final NotificationChannel channel = new NotificationChannel( + NOTIFICATION_CHANNEL_ID, contentTitle, NotificationManager.IMPORTANCE_LOW); + channel.enableLights(false); + channel.enableVibration(false); + + final NotificationManager notificationManager = + context.getSystemService(NotificationManager.class); + if (notificationManager != null) { + notificationManager.createNotificationChannel(channel); + } + } + + /** + * Return Foreground info. This object contains a Notification and notification id that should + * be displayed in the context of a foreground service. + * This method should not be invoked by WorkManager in Android S+ devices. + */ + @NonNull + public static ForegroundInfo getForegroundInfo(@NonNull Context context) { + if (SdkLevel.isAtLeastS()) { + Log.w(TAG, "Picker Sync notifications should not be displayed in S+ devices."); + } + return new ForegroundInfo(NOTIFICATION_ID, getNotification(context)); + } + + /** + * Create a notification to display when Picker sync is happening. + */ + private static Notification getNotification(@NonNull Context context) { + final Resources resources = context.getResources(); + final String contentTitle = resources.getString(R.string.picker_sync_notification_title); + final String contentText = resources.getString(R.string.picker_sync_notification_text); + + return new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(R.drawable.picker_app_icon) + .setContentTitle(contentTitle) + .setContentText(contentText) + .setPriority(NotificationCompat.PRIORITY_MIN) + .setVisibility(NotificationCompat.VISIBILITY_SECRET) + .setSilent(true) + .setTimeoutAfter(NOTIFICATION_TIMEOUT_MILLIS) + .build(); + } +} diff --git a/src/com/android/providers/media/photopicker/sync/ProactiveSyncWorker.java b/src/com/android/providers/media/photopicker/sync/ProactiveSyncWorker.java index 8a9297f82..dff247677 100644 --- a/src/com/android/providers/media/photopicker/sync/ProactiveSyncWorker.java +++ b/src/com/android/providers/media/photopicker/sync/ProactiveSyncWorker.java @@ -28,11 +28,13 @@ import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; +import androidx.work.ForegroundInfo; import androidx.work.ListenableWorker; import androidx.work.Worker; import androidx.work.WorkerParameters; import com.android.providers.media.photopicker.PickerSyncController; +import com.android.providers.media.photopicker.util.exceptions.RequestObsoleteException; /** * This is a {@link Worker} class responsible for proactively syncing media with the correct sync @@ -40,6 +42,7 @@ import com.android.providers.media.photopicker.PickerSyncController; */ public class ProactiveSyncWorker extends Worker { private static final String TAG = "PSyncWorker"; + private final Context mContext; /** * Creates an instance of the {@link Worker}. @@ -49,6 +52,7 @@ public class ProactiveSyncWorker extends Worker { */ public ProactiveSyncWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); + mContext = context; } @NonNull @@ -67,6 +71,7 @@ public class ProactiveSyncWorker extends Worker { localSyncTracker.createSyncFuture(getId()); // Complete sync and mark work tracker as finished. + checkIsWorkerStopped(); PickerSyncController.getInstanceOrThrow().syncAllMediaFromLocalProvider(); localSyncTracker.markSyncCompleted(getId()); Log.i(TAG, "Completed picker proactive sync complete from local provider."); @@ -77,12 +82,13 @@ public class ProactiveSyncWorker extends Worker { cloudSyncTracker.createSyncFuture(getId()); // Complete sync and mark work tracker as finished. + checkIsWorkerStopped(); PickerSyncController.getInstanceOrThrow().syncAllMediaFromCloudProvider(); cloudSyncTracker.markSyncCompleted(getId()); Log.i(TAG, "Completed picker proactive sync complete from cloud provider."); } return ListenableWorker.Result.success(); - } catch (IllegalStateException e) { + } catch (IllegalStateException | RequestObsoleteException e) { Log.e(TAG, "Could not complete proactive sync for sync source: " + syncSource, e); // Mark all pending syncs as finished and set failure result. @@ -90,4 +96,26 @@ public class ProactiveSyncWorker extends Worker { return ListenableWorker.Result.failure(); } } + + private void checkIsWorkerStopped() throws RequestObsoleteException { + if (isStopped()) { + throw new RequestObsoleteException("Work is stopped " + getId()); + } + } + + @Override + @NonNull + public ForegroundInfo getForegroundInfo() { + Log.e(TAG, "Proactive Sync Worker should not run as an expedited task"); + return PickerSyncNotificationHelper.getForegroundInfo(mContext); + } + + @Override + public void onStopped() { + Log.w(TAG, "Worker is stopped. Clearing all pending futures. It's possible that the sync " + + "still finishes running if it has started already."); + final int syncSource = getInputData() + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, /* defaultValue */ SYNC_LOCAL_AND_CLOUD); + markSyncAsComplete(syncSource, getId()); + } } diff --git a/src/com/android/providers/media/photopicker/ui/AlbumGridHolder.java b/src/com/android/providers/media/photopicker/ui/AlbumGridHolder.java index a9d42d6d2..a90f6388b 100644 --- a/src/com/android/providers/media/photopicker/ui/AlbumGridHolder.java +++ b/src/com/android/providers/media/photopicker/ui/AlbumGridHolder.java @@ -16,6 +16,7 @@ package com.android.providers.media.photopicker.ui; +import android.provider.CloudMediaProviderContract; import android.text.TextUtils; import android.view.View; import android.widget.ImageView; @@ -38,6 +39,7 @@ class AlbumGridHolder extends RecyclerView.ViewHolder { private final ImageLoader mImageLoader; private final ImageView mIconThumb; + private final ImageView mIconDefaultThumb; private final TextView mAlbumName; private final TextView mItemCount; private final boolean mHasMimeTypeFilter; @@ -50,6 +52,7 @@ class AlbumGridHolder extends RecyclerView.ViewHolder { super(itemView); mIconThumb = itemView.findViewById(R.id.icon_thumbnail); + mIconDefaultThumb = itemView.findViewById(R.id.icon_default_thumbnail); mAlbumName = itemView.findViewById(R.id.album_name); mItemCount = itemView.findViewById(R.id.item_count); mImageLoader = imageLoader; @@ -60,7 +63,16 @@ class AlbumGridHolder extends RecyclerView.ViewHolder { void bind(@NonNull Category category) { int position = getAbsoluteAdapterPosition(); itemView.setOnClickListener(v -> mOnAlbumClickListener.onAlbumClick(category, position)); - mImageLoader.loadAlbumThumbnail(category, mIconThumb); + + // Show default thumbnail icons if merged album is empty. + int defaultResId = -1; + if (CloudMediaProviderContract.AlbumColumns.ALBUM_ID_FAVORITES.equals(category.getId())) { + defaultResId = R.drawable.thumbnail_favorites; + } else if (CloudMediaProviderContract.AlbumColumns.ALBUM_ID_VIDEOS + .equals(category.getId())) { + defaultResId = R.drawable.thumbnail_videos; + } + mImageLoader.loadAlbumThumbnail(category, mIconThumb, defaultResId, mIconDefaultThumb); mAlbumName.setText(category.getDisplayName(itemView.getContext())); // Check whether there is a mime type filter or not. If yes, hide the item count. Otherwise, // show the item count and update the count. diff --git a/src/com/android/providers/media/photopicker/ui/AlbumsTabFragment.java b/src/com/android/providers/media/photopicker/ui/AlbumsTabFragment.java index b973c3bc5..7d67abfbe 100644 --- a/src/com/android/providers/media/photopicker/ui/AlbumsTabFragment.java +++ b/src/com/android/providers/media/photopicker/ui/AlbumsTabFragment.java @@ -15,8 +15,6 @@ */ package com.android.providers.media.photopicker.ui; -import static com.android.providers.media.photopicker.DataLoaderThread.TOKEN; - import android.content.Context; import android.os.Bundle; import android.view.View; @@ -27,7 +25,6 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import com.android.providers.media.R; -import com.android.providers.media.photopicker.DataLoaderThread; import com.android.providers.media.photopicker.util.LayoutModeUtils; import java.util.ArrayList; @@ -106,11 +103,4 @@ public class AlbumsTabFragment extends TabFragment { ft.replace(R.id.fragment_container, fragment); ft.commitAllowingStateLoss(); } - - @Override - public void onDestroy() { - super.onDestroy(); - // Clear queued tasks in handler. - DataLoaderThread.getHandler().removeCallbacksAndMessages(TOKEN); - } }
\ No newline at end of file diff --git a/src/com/android/providers/media/photopicker/ui/ImageLoader.java b/src/com/android/providers/media/photopicker/ui/ImageLoader.java index 0d77b8287..08f25d98a 100644 --- a/src/com/android/providers/media/photopicker/ui/ImageLoader.java +++ b/src/com/android/providers/media/photopicker/ui/ImageLoader.java @@ -26,6 +26,7 @@ import android.net.Uri; import android.provider.CloudMediaProviderContract; import android.provider.MediaStore; import android.util.Log; +import android.view.View; import android.widget.ImageView; import androidx.annotation.NonNull; @@ -71,12 +72,24 @@ public class ImageLoader { * @param category the album * @param imageView the imageView shows the thumbnail */ - public void loadAlbumThumbnail(@NonNull Category category, @NonNull ImageView imageView) { + public void loadAlbumThumbnail(@NonNull Category category, @NonNull ImageView imageView, + int defaultThumbnailRes, @NonNull ImageView defaultIcon) { // Always show all thumbnails as bitmap images instead of drawables // This is to ensure that we do not animate any thumbnail (for eg GIF) // TODO(b/194285082): Use drawable instead of bitmap, as it saves memory. - loadWithGlide(getBitmapRequestBuilder(category.getCoverUri()), THUMBNAIL_OPTION, - /* signature */ null, imageView); + if (category.getCoverUri() != null || defaultThumbnailRes == -1) { + defaultIcon.setVisibility(View.GONE); + imageView.setVisibility(View.VISIBLE); + + loadWithGlide(getBitmapRequestBuilder(category.getCoverUri()), THUMBNAIL_OPTION, + /* signature */ null, imageView); + } else { + imageView.setVisibility(View.INVISIBLE); + defaultIcon.setVisibility(View.VISIBLE); + + loadWithGlide(getDrawableRequestBuilder(mContext.getDrawable(defaultThumbnailRes)), + THUMBNAIL_OPTION, /* signature */ null, defaultIcon); + } } /** diff --git a/src/com/android/providers/media/photopicker/ui/PhotosTabAdapter.java b/src/com/android/providers/media/photopicker/ui/PhotosTabAdapter.java index 3588fc378..5f518646a 100644 --- a/src/com/android/providers/media/photopicker/ui/PhotosTabAdapter.java +++ b/src/com/android/providers/media/photopicker/ui/PhotosTabAdapter.java @@ -103,6 +103,10 @@ class PhotosTabAdapter extends TabAdapter { final boolean isSelected = mSelection.canSelectMultiple() && mSelection.isItemSelected(item); + if (isSelected) { + mSelection.addCheckedItemIndex(item, position); + } + mediaItemVH.bind(item, isSelected); // We also need to set Item as a tag so that OnClick/OnLongClickListeners can then @@ -191,4 +195,4 @@ class PhotosTabAdapter extends TabAdapter { boolean onItemLongClick(@NonNull View view, int position); } -} +}
\ No newline at end of file diff --git a/src/com/android/providers/media/photopicker/ui/PhotosTabFragment.java b/src/com/android/providers/media/photopicker/ui/PhotosTabFragment.java index 2050cae0e..d8421325f 100644 --- a/src/com/android/providers/media/photopicker/ui/PhotosTabFragment.java +++ b/src/com/android/providers/media/photopicker/ui/PhotosTabFragment.java @@ -15,7 +15,6 @@ */ package com.android.providers.media.photopicker.ui; -import static com.android.providers.media.photopicker.DataLoaderThread.TOKEN; import static com.android.providers.media.photopicker.ui.ItemsAction.ACTION_LOAD_NEXT_PAGE; import static com.android.providers.media.photopicker.ui.ItemsAction.ACTION_REFRESH_ITEMS; import static com.android.providers.media.photopicker.ui.ItemsAction.ACTION_VIEW_CREATED; @@ -44,7 +43,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.providers.media.R; -import com.android.providers.media.photopicker.DataLoaderThread; import com.android.providers.media.photopicker.data.PaginationParameters; import com.android.providers.media.photopicker.data.model.Category; import com.android.providers.media.photopicker.data.model.Item; @@ -87,7 +85,6 @@ public class PhotosTabFragment extends TabFragment { private final Object mHideProgressBarToken = new Object(); - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -133,6 +130,7 @@ public class PhotosTabFragment extends TabFragment { if (savedInstanceState == null) { initProgressBar(view); } + mSelection.clearCheckedItemList(); final PhotosTabAdapter adapter = new PhotosTabAdapter(showRecentSection, mSelection, mImageLoader, mOnMediaItemClickListener, /* lifecycleOwner */ this, @@ -153,7 +151,7 @@ public class PhotosTabFragment extends TabFragment { ACTION_VIEW_CREATED, new PaginationParameters( mPageSize, - /* dateBeforeMs */ -1, + /* dateBeforeMs */ Long.MIN_VALUE, /* rowId */ -1)) .observe(this, itemListResult -> { onChangeMediaItems(itemListResult, adapter); @@ -170,7 +168,7 @@ public class PhotosTabFragment extends TabFragment { ACTION_VIEW_CREATED, new PaginationParameters( mPageSize, - /* dateBeforeMs */ -1, + /* dateBeforeMs */ Long.MIN_VALUE, /* rowId */ -1)) .observe(this, itemListResult -> { onChangeMediaItems(itemListResult, adapter); @@ -190,8 +188,21 @@ public class PhotosTabFragment extends TabFragment { if (mIsCloudMediaInPhotoPickerEnabled) { setOnScrollListenerForRecyclerView(); } - } + // uncheck the unavailable items at UI those are no longer available in the selection list + getPickerActivity().isItemPhotoGridViewChanged() + .observe(this, isItemViewChanged -> { + if (isItemViewChanged) { + // To re-bind the view just to uncheck the unavailable media items at UI + // Size of mCheckItems is going to be constant ( Iterating over mCheckItems + // is not a heavy operation) + for (Integer index : mSelection.getCheckedItemsIndexes()) { + adapter.notifyItemChanged(index); + } + } + } + ); + } private void initProgressBar(@NonNull View view) { // Check feature flag for cloud media and if it is not true then hide progress bar and @@ -281,7 +292,6 @@ public class PhotosTabFragment extends TabFragment { @Override public void onResume() { super.onResume(); - final String title; final LayoutModeUtils.Mode layoutMode; final boolean shouldHideProfileButton; @@ -311,7 +321,8 @@ public class PhotosTabFragment extends TabFragment { mPickerViewModel.getPaginatedItemsForAction( ACTION_REFRESH_ITEMS, new PaginationParameters(firstVisibleItemPosition - + PaginationParameters.PAGINATION_PAGE_SIZE_ITEMS, -1, -1)); + + PaginationParameters.PAGINATION_PAGE_SIZE_ITEMS, + /*dateBeforeMs*/ Long.MIN_VALUE, -1)); } } } @@ -325,7 +336,11 @@ public class PhotosTabFragment extends TabFragment { } else { adapter.setMediaItems(itemList.getItems(), itemList.getAction()); // Handle emptyView's visibility - updateVisibilityForEmptyView(/* shouldShowEmptyView */ itemList.getItems().size() == 0); + boolean shouldShowEmptyView = (itemList.getItems().size() == 0); + updateVisibilityForEmptyView(shouldShowEmptyView); + if (shouldShowEmptyView) { + mPickerViewModel.setEmptyPageDisplayed(true); + } } mIsCurrentPageLoading = false; mAtLeastOnePageLoaded = true; @@ -342,12 +357,15 @@ public class PhotosTabFragment extends TabFragment { new PhotosTabAdapter.OnMediaItemClickListener() { @Override public void onItemClick(@NonNull View view, int position) { + if (mSelection.canSelectMultiple()) { final boolean isSelectedBefore = view.isSelected(); if (isSelectedBefore) { mSelection.removeSelectedItem((Item) view.getTag()); + mSelection.removeCheckedItemIndex((Item) view.getTag()); } else { + mSelection.addCheckedItemIndex((Item) view.getTag(), position); if (!mSelection.isSelectionAllowed()) { final int maxCount = mSelection.getMaxSelectionLimit(); final CharSequence quantityText = @@ -366,6 +384,7 @@ public class PhotosTabFragment extends TabFragment { } } view.setSelected(!isSelectedBefore); + // There is an issue b/223695510 about not selected in Accessibility mode. // It only says selected state, but it doesn't say not selected state. // Add the not selected only to avoid that it says selected twice. @@ -487,11 +506,10 @@ public class PhotosTabFragment extends TabFragment { mProgressBar.setVisibility(View.VISIBLE); } } + @Override public void onDestroy() { super.onDestroy(); mMainThreadHandler.removeCallbacksAndMessages(mHideProgressBarToken); - // Clear queued tasks in handler. - DataLoaderThread.getHandler().removeCallbacksAndMessages(TOKEN); } -} +}
\ No newline at end of file diff --git a/src/com/android/providers/media/photopicker/ui/TabAdapter.java b/src/com/android/providers/media/photopicker/ui/TabAdapter.java index 9b2c6efb7..35db5801e 100644 --- a/src/com/android/providers/media/photopicker/ui/TabAdapter.java +++ b/src/com/android/providers/media/photopicker/ui/TabAdapter.java @@ -317,7 +317,7 @@ public abstract class TabAdapter extends RecyclerView.Adapter<RecyclerView.ViewH mDismissButton.setOnClickListener(v -> onBannerEventListener.onDismissButtonClick()); - if (banner.mActionButtonText != -1) { + if (banner.mActionButtonText != -1 && onBannerEventListener.shouldShowActionButton()) { mActionButton.setText(banner.mActionButtonText); mActionButton.setVisibility(View.VISIBLE); mActionButton.setOnClickListener(v -> onBannerEventListener.onActionButtonClick()); @@ -328,18 +328,14 @@ public abstract class TabAdapter extends RecyclerView.Adapter<RecyclerView.ViewH } private enum Banner { - // TODO(b/274426228): Replace `CLOUD_MEDIA_AVAILABLE` `mActionButtonText` from `-1` to - // `R.string.picker_banner_cloud_change_account_button`, post change cloud account - // functionality implementation from the Picker settings (b/261999521). CLOUD_MEDIA_AVAILABLE(R.string.picker_banner_cloud_first_time_available_title, - R.string.picker_banner_cloud_first_time_available_desc, /* no action button */ -1), + R.string.picker_banner_cloud_first_time_available_desc, + R.string.picker_banner_cloud_change_account_button), ACCOUNT_UPDATED(R.string.picker_banner_cloud_account_changed_title, R.string.picker_banner_cloud_account_changed_desc, /* no action button */ -1), - // TODO(b/274426228): Replace `CHOOSE_ACCOUNT` `mActionButtonText` from `-1` to - // `R.string.picker_banner_cloud_choose_account_button`, post change cloud account - // functionality implementation from the Picker settings (b/261999521). CHOOSE_ACCOUNT(R.string.picker_banner_cloud_choose_account_title, - R.string.picker_banner_cloud_choose_account_desc, /* no action button */ -1), + R.string.picker_banner_cloud_choose_account_desc, + R.string.picker_banner_cloud_choose_account_button), CHOOSE_APP(R.string.picker_banner_cloud_choose_app_title, R.string.picker_banner_cloud_choose_app_desc, R.string.picker_banner_cloud_choose_app_button); @@ -395,5 +391,9 @@ public abstract class TabAdapter extends RecyclerView.Adapter<RecyclerView.ViewH } void onBannerAdded(); + + default boolean shouldShowActionButton() { + return true; + } } } diff --git a/src/com/android/providers/media/photopicker/ui/TabFragment.java b/src/com/android/providers/media/photopicker/ui/TabFragment.java index 820993e31..159a97ce2 100644 --- a/src/com/android/providers/media/photopicker/ui/TabFragment.java +++ b/src/com/android/providers/media/photopicker/ui/TabFragment.java @@ -24,6 +24,7 @@ import static com.android.providers.media.photopicker.ui.TabAdapter.ITEM_TYPE_SE import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; @@ -468,7 +469,15 @@ public abstract class TabFragment extends Fragment { @Override public void onActionButtonClick() { dismissBanner(); - getPickerActivity().startSettingsActivity(); + + final Intent accountChangeIntent = + mPickerViewModel.getChooseCloudMediaAccountActivityIntent(); + + if (accountChangeIntent != null) { + getPickerActivity().startActivity(accountChangeIntent); + } else { + getPickerActivity().startSettingsActivity(); + } } @Override @@ -513,6 +522,11 @@ public abstract class TabFragment extends Fragment { void dismissBanner() { mPickerViewModel.onUserDismissedCloudMediaAvailableBanner(); } + + @Override + public boolean shouldShowActionButton() { + return mPickerViewModel.getChooseCloudMediaAccountActivityIntent() != null; + } }; protected final OnBannerEventListener mOnAccountUpdatedBannerEventListener = @@ -529,5 +543,10 @@ public abstract class TabFragment extends Fragment { void dismissBanner() { mPickerViewModel.onUserDismissedChooseAccountBanner(); } + + @Override + public boolean shouldShowActionButton() { + return mPickerViewModel.getChooseCloudMediaAccountActivityIntent() != null; + } }; } diff --git a/src/com/android/providers/media/photopicker/ui/remotepreview/RemotePreviewSession.java b/src/com/android/providers/media/photopicker/ui/remotepreview/RemotePreviewSession.java index 7536f6e21..cac25f587 100644 --- a/src/com/android/providers/media/photopicker/ui/remotepreview/RemotePreviewSession.java +++ b/src/com/android/providers/media/photopicker/ui/remotepreview/RemotePreviewSession.java @@ -268,6 +268,12 @@ final class RemotePreviewSession { case PLAYBACK_STATE_BUFFERING: mPreviewVideoHolder.getCircularProgressIndicator().setVisibility(View.VISIBLE); return; + case PLAYBACK_STATE_COMPLETED: + // TODO(b/296543163): Investigate CloudMediaProviderContract for future OEM + // implementers. Should the provider be expected to loop the video themselves + // instead of ending the playback state? + requestPlayMedia(); + return; default: } } @@ -375,7 +381,8 @@ final class RemotePreviewSession { // media size, then we hide the thumbnail view. mPreviewVideoHolder.getPlayerContainer().setVisibility(View.INVISIBLE); mPreviewVideoHolder.getThumbnailView().setVisibility(View.VISIBLE); - mPreviewVideoHolder.getPlayerControlsRoot().setVisibility(View.GONE); + updatePlayerControlsVisibilityState( + mPlayerControlsVisibilityStatus.shouldShowPlayerControls()); mPreviewVideoHolder.getCircularProgressIndicator().setVisibility(View.GONE); updatePlayPauseButtonState(false /* isPlaying */); @@ -450,7 +457,11 @@ final class RemotePreviewSession { mIsAccessibilityEnabled = enabled; mPreviewVideoHolder.getPlayerContainer().setOnClickListener( mIsAccessibilityEnabled ? null : mPlayerContainerClickListener); - updatePlayerControlsVisibilityState(mIsAccessibilityEnabled); + if (mIsAccessibilityEnabled) { + updatePlayerControlsVisibilityState(/* visible= */ true); + } else { + hidePlayerControlsWithDelay(); + } } private void updatePlayPauseButtonState(boolean isPlaying) { diff --git a/src/com/android/providers/media/photopicker/ui/settings/SettingsCloudMediaViewModel.java b/src/com/android/providers/media/photopicker/ui/settings/SettingsCloudMediaViewModel.java index 346eed309..ca9be634f 100644 --- a/src/com/android/providers/media/photopicker/ui/settings/SettingsCloudMediaViewModel.java +++ b/src/com/android/providers/media/photopicker/ui/settings/SettingsCloudMediaViewModel.java @@ -56,6 +56,7 @@ import java.util.List; public class SettingsCloudMediaViewModel extends ViewModel { static final String NONE_PREF_KEY = "none"; private static final String TAG = "SettingsFragVM"; + private static final long GET_ACCOUNT_NAME_TIMEOUT_IN_MILLIS = 10000L; @NonNull private final Context mContext; @@ -196,7 +197,8 @@ public class SettingsCloudMediaViewModel extends ViewModel { } else { try { final String accountName = getCloudMediaAccountName( - mUserId.getContentResolver(mContext), currentProviderAuthority); + mUserId.getContentResolver(mContext), currentProviderAuthority, + GET_ACCOUNT_NAME_TIMEOUT_IN_MILLIS); return new CloudMediaProviderAccount(currentProviderAuthority, accountName); } catch (Exception e) { Log.w(TAG, "Failed to fetch account name from the cloud media provider.", e); diff --git a/src/com/android/providers/media/photopicker/util/CloudProviderUtils.java b/src/com/android/providers/media/photopicker/util/CloudProviderUtils.java index 741755bdf..a859ba304 100644 --- a/src/com/android/providers/media/photopicker/util/CloudProviderUtils.java +++ b/src/com/android/providers/media/photopicker/util/CloudProviderUtils.java @@ -28,8 +28,12 @@ import static android.provider.MediaStore.GET_CLOUD_PROVIDER_RESULT; import static android.provider.MediaStore.PICKER_MEDIA_INIT_CALL; import static android.provider.MediaStore.SET_CLOUD_PROVIDER_CALL; +import static com.android.providers.media.PickerUriResolver.getMediaCollectionInfoUri; + import static java.util.Collections.emptyList; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import android.annotation.DurationMillisLong; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; @@ -55,6 +59,9 @@ import com.android.providers.media.photopicker.data.model.UserId; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; /** * Utility methods for retrieving available and/or allowlisted Cloud Providers. @@ -248,23 +255,48 @@ public class CloudProviderUtils { } /** + * @param resolver {@link ContentResolver} for the related user + * @param cloudMediaProviderAuthority authority {@link String} of the {@link CloudMediaProvider} + * @param timeout timeout in milliseconds for this query (<= 0 for timeout) * @return the current cloud media account name for the {@link CloudMediaProvider} with the * given {@code cloudMediaProviderAuthority}. */ @Nullable public static String getCloudMediaAccountName(@NonNull ContentResolver resolver, - @Nullable String cloudMediaProviderAuthority) { + @Nullable String cloudMediaProviderAuthority, @DurationMillisLong long timeout) + throws ExecutionException, InterruptedException, TimeoutException { if (cloudMediaProviderAuthority == null) { return null; } - try (ContentProviderClient client = - resolver.acquireContentProviderClient(cloudMediaProviderAuthority)) { - final Bundle out = client.call(METHOD_GET_MEDIA_COLLECTION_INFO, /* arg */ null, - /* extras */ null); - return out.getString(ACCOUNT_NAME); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); + CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { + final Bundle out = resolver.call(getMediaCollectionInfoUri(cloudMediaProviderAuthority), + METHOD_GET_MEDIA_COLLECTION_INFO, /* arg */ null, /* extras */ null); + return (out == null) ? null : out.getString(ACCOUNT_NAME); + }); + + return (timeout > 0) ? future.get(timeout, MILLISECONDS) : future.get(); + } + + /** + * @param resolver {@link ContentResolver} for the related user + * @param cloudMediaProviderAuthority authority {@link String} of the {@link CloudMediaProvider} + * @param timeout timeout in milliseconds for this query (<= 0 for timeout) + * @return the current cloud media collection info for the {@link CloudMediaProvider} with the + * given {@code cloudMediaProviderAuthority}. + */ + @Nullable + public static Bundle getCloudMediaCollectionInfo(@NonNull ContentResolver resolver, + @Nullable String cloudMediaProviderAuthority, @DurationMillisLong long timeout) + throws ExecutionException, InterruptedException, TimeoutException { + if (cloudMediaProviderAuthority == null) { + return null; } + + CompletableFuture<Bundle> future = CompletableFuture.supplyAsync(() -> + resolver.call(getMediaCollectionInfoUri(cloudMediaProviderAuthority), + METHOD_GET_MEDIA_COLLECTION_INFO, /* arg */ null, /* extras */ null)); + + return (timeout > 0) ? future.get(timeout, MILLISECONDS) : future.get(); } } diff --git a/src/com/android/providers/media/photopicker/viewmodel/BannerController.java b/src/com/android/providers/media/photopicker/viewmodel/BannerController.java index 5b070a3c8..5d8afe99e 100644 --- a/src/com/android/providers/media/photopicker/viewmodel/BannerController.java +++ b/src/com/android/providers/media/photopicker/viewmodel/BannerController.java @@ -19,14 +19,17 @@ package com.android.providers.media.photopicker.viewmodel; import static android.provider.MediaStore.getCurrentCloudProvider; import static com.android.providers.media.photopicker.util.CloudProviderUtils.getAvailableCloudProviders; -import static com.android.providers.media.photopicker.util.CloudProviderUtils.getCloudMediaAccountName; +import static com.android.providers.media.photopicker.util.CloudProviderUtils.getCloudMediaCollectionInfo; import static com.android.providers.media.photopicker.util.CloudProviderUtils.getProviderLabelForUser; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; +import android.os.Bundle; import android.os.Looper; import android.os.UserHandle; +import android.provider.CloudMediaProviderContract.MediaCollectionInfo; import android.text.TextUtils; import android.util.AtomicFile; import android.util.Log; @@ -44,6 +47,8 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; /** * Banner Controller to store and handle the banner data per user for @@ -64,6 +69,7 @@ class BannerController { * {@link android.provider.CloudMediaProvider}. */ private static final String ACCOUNT_NAME = "account_name"; + private static final long GET_CLOUD_MEDIA_COLLECTION_INFO_TIMEOUT_IN_MILLIS = 100L; private final Context mContext; private final UserHandle mUserHandle; @@ -83,6 +89,9 @@ class BannerController { // Label of the current cloud media provider private String mCmpLabel; + // Account selection activity intent of the current cloud media provider + private Intent mChooseCloudMediaAccountActivityIntent; + // Boolean 'Choose App' banner visibility private boolean mShowChooseAppBanner; @@ -130,7 +139,9 @@ class BannerController { * block the UI thread on the heavy Binder calls to fetch the cloud media provider info. */ private void initialise() { - final String cmpAuthority, cmpAccountName; + String cmpAuthority = null, cmpAccountName = null; + mCmpLabel = null; + mChooseCloudMediaAccountActivityIntent = null; // TODO(b/245746037): Remove try-catch for the RuntimeException. // Under the hood MediaStore.getCurrentCloudProvider() makes an IPC call to the primary // MediaProvider process, where we currently perform a UID check (making sure that @@ -149,14 +160,23 @@ class BannerController { UserId.of(mUserHandle).getContentResolver(mContext); cmpAuthority = getCurrentCloudProvider(contentResolver); mCmpLabel = getProviderLabelForUser(mContext, mUserHandle, cmpAuthority); - cmpAccountName = getCloudMediaAccountName(contentResolver, cmpAuthority); + final Bundle cloudMediaCollectionInfo = getCloudMediaCollectionInfo(contentResolver, + cmpAuthority, GET_CLOUD_MEDIA_COLLECTION_INFO_TIMEOUT_IN_MILLIS); + if (cloudMediaCollectionInfo != null) { + cmpAccountName = cloudMediaCollectionInfo.getString( + MediaCollectionInfo.ACCOUNT_NAME); + mChooseCloudMediaAccountActivityIntent = cloudMediaCollectionInfo.getParcelable( + MediaCollectionInfo.ACCOUNT_CONFIGURATION_INTENT); + } // Not logging the account name due to privacy concerns Log.d(TAG, "Current CloudMediaProvider authority: " + cmpAuthority + ", label: " + mCmpLabel); - } catch (PackageManager.NameNotFoundException | RuntimeException e) { + } catch (PackageManager.NameNotFoundException | RuntimeException | ExecutionException + | InterruptedException | TimeoutException e) { Log.w(TAG, "Could not fetch the current CloudMediaProvider", e); - resetToDefault(); + updateCloudProviderDataMap(cmpAuthority, cmpAccountName); + clearBanners(); return; } @@ -213,15 +233,6 @@ class BannerController { } /** - * Reset all the controller data to their default values. - */ - private void resetToDefault() { - mCloudProviderDataMap.clear(); - mCmpLabel = null; - clearBanners(); - } - - /** * Clear all banners * * Reset all should show banner {@code boolean} values to {@code false}. @@ -263,6 +274,15 @@ class BannerController { } /** + * @return the account selection activity {@link Intent} of the current + * {@link android.provider.CloudMediaProvider}. + */ + @Nullable + Intent getChooseCloudMediaAccountActivityIntent() { + return mChooseCloudMediaAccountActivityIntent; + } + + /** * @return the 'Choose App' banner visibility {@link #mShowChooseAppBanner}. */ boolean shouldShowChooseAppBanner() { @@ -385,6 +405,12 @@ class BannerController { private void persistCloudProviderInfo(@Nullable String cmpAuthority, @Nullable String cmpAccountName) { + updateCloudProviderDataMap(cmpAuthority, cmpAccountName); + updateCloudProviderDataFile(); + } + + private void updateCloudProviderDataMap(@Nullable String cmpAuthority, + @Nullable String cmpAccountName) { mCloudProviderDataMap.clear(); if (cmpAuthority != null) { mCloudProviderDataMap.put(AUTHORITY, cmpAuthority); @@ -392,8 +418,6 @@ class BannerController { if (cmpAccountName != null) { mCloudProviderDataMap.put(ACCOUNT_NAME, cmpAccountName); } - - updateCloudProviderDataFile(); } @VisibleForTesting diff --git a/src/com/android/providers/media/photopicker/viewmodel/BannerManager.java b/src/com/android/providers/media/photopicker/viewmodel/BannerManager.java index b871cbff3..a726d0bf1 100644 --- a/src/com/android/providers/media/photopicker/viewmodel/BannerManager.java +++ b/src/com/android/providers/media/photopicker/viewmodel/BannerManager.java @@ -20,6 +20,7 @@ import static com.android.providers.media.photopicker.DataLoaderThread.TOKEN; import android.annotation.UserIdInt; import android.content.Context; +import android.content.Intent; import android.os.UserHandle; import android.util.Log; @@ -46,6 +47,8 @@ class BannerManager { private final MutableLiveData<String> mCloudMediaProviderLabel = new MutableLiveData<>(); // Account name of the current CloudMediaProvider of the current user private final MutableLiveData<String> mCloudMediaAccountName = new MutableLiveData<>(); + // Account selection activity intent of the current CloudMediaProvider of the current user + private Intent mChooseCloudMediaAccountActivityIntent = null; // Boolean Choose App Banner visibility private final MutableLiveData<Boolean> mShowChooseAppBanner = new MutableLiveData<>(false); @@ -101,6 +104,24 @@ class BannerManager { } /** + * @return the account selection activity {@link Intent} of the current + * {@link android.provider.CloudMediaProvider}. + */ + @Nullable + Intent getChooseCloudMediaAccountActivityIntent() { + return mChooseCloudMediaAccountActivityIntent; + } + + + /** + * Update the account selection activity {@link Intent} of the current + * {@link android.provider.CloudMediaProvider}. + */ + void setChooseCloudMediaAccountActivityIntent(Intent intent) { + mChooseCloudMediaAccountActivityIntent = intent; + } + + /** * @return a {@link LiveData} that holds the value (once it's fetched) of the account name * of the current {@link android.provider.CloudMediaProvider}. */ @@ -291,6 +312,8 @@ class BannerManager { .postValue(bannerController.getCloudMediaProviderLabel()); getCloudMediaAccountNameLiveData() .postValue(bannerController.getCloudMediaProviderAccountName()); + setChooseCloudMediaAccountActivityIntent( + bannerController.getChooseCloudMediaAccountActivityIntent()); shouldShowChooseAppBannerLiveData() .postValue(bannerController.shouldShowChooseAppBanner()); shouldShowCloudMediaAvailableBannerLiveData() diff --git a/src/com/android/providers/media/photopicker/viewmodel/PickerViewModel.java b/src/com/android/providers/media/photopicker/viewmodel/PickerViewModel.java index b4bfb24bd..5e1e05dd8 100644 --- a/src/com/android/providers/media/photopicker/viewmodel/PickerViewModel.java +++ b/src/com/android/providers/media/photopicker/viewmodel/PickerViewModel.java @@ -43,9 +43,12 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; import android.database.ContentObserver; import android.database.Cursor; import android.os.CancellationSignal; +import android.os.Handler; +import android.os.Looper; import android.provider.MediaStore; import android.text.TextUtils; import android.util.Log; @@ -61,6 +64,7 @@ import androidx.lifecycle.Observer; import com.android.internal.logging.InstanceId; import com.android.internal.logging.InstanceIdSequence; +import com.android.modules.utils.BackgroundThread; import com.android.modules.utils.build.SdkLevel; import com.android.providers.media.ConfigStore; import com.android.providers.media.MediaApplication; @@ -96,12 +100,16 @@ public class PickerViewModel extends AndroidViewModel { private static final int INSTANCE_ID_MAX = 1 << 15; private static final int DELAY_MILLIS = 0; + // Token for the tasks to load the category items in the data loader thread's queue + private final Object mLoadCategoryItemsThreadToken = new Object(); + @NonNull @SuppressLint("StaticFieldLeak") private final Context mAppContext; private final Selection mSelection; private final MuteStatus mMuteStatus; + public boolean mEmptyPageDisplayed = false; // TODO(b/193857982): We keep these four data sets now, we may need to find a way to reduce the // data set to reduce memories. @@ -146,7 +154,6 @@ public class PickerViewModel extends AndroidViewModel { // Note - Must init banner manager on mIsUserSelectForApp / mIsLocalOnly updates private boolean mIsUserSelectForApp; private boolean mIsLocalOnly; - private boolean mIsAllItemsLoaded = false; private boolean mIsAllCategoryItemsLoaded = false; private boolean mIsNotificationForUpdateReceived = false; private CancellationSignal mCancellationSignal = new CancellationSignal(); @@ -188,13 +195,20 @@ public class PickerViewModel extends AndroidViewModel { // Signal ContentProvider to cancel currently running task. mCancellationSignal.cancel(); - // Clear queued tasks in handler. - DataLoaderThread.getHandler().removeCallbacksAndMessages(TOKEN); + clearQueuedTasksInDataLoaderThread(); } private void onNotificationReceived() { Log.d(TAG, "Notification for media update has been received"); mIsNotificationForUpdateReceived = true; + if (mEmptyPageDisplayed && mConfigStore.isCloudMediaInPhotoPickerEnabled()) { + (new Handler(Looper.getMainLooper())).post(() -> { + Log.d(TAG, "Refreshing UI to display new items."); + mEmptyPageDisplayed = false; + getPaginatedItemsForAction(ACTION_REFRESH_ITEMS, + new PaginationParameters(mItemsPageSize, -1, -1)); + }); + } } @VisibleForTesting @@ -232,6 +246,10 @@ public class PickerViewModel extends AndroidViewModel { mConfigStore = configStore; } + public void setEmptyPageDisplayed(boolean emptyPageDisplayed) { + mEmptyPageDisplayed = emptyPageDisplayed; + } + /** * @return the {@link ConfigStore} for this context. */ @@ -298,6 +316,15 @@ public class PickerViewModel extends AndroidViewModel { } /** + * @return the account selection activity {@link Intent} of the current + * {@link android.provider.CloudMediaProvider}. + */ + @Nullable + public Intent getChooseCloudMediaAccountActivityIntent() { + return mBannerManager.getChooseCloudMediaAccountActivityIntent(); + } + + /** * Reset to personal profile mode. */ @UiThread @@ -325,8 +352,7 @@ public class PickerViewModel extends AndroidViewModel { // Post 'should refresh UI live data' value as false to avoid unnecessary repetitive resets mShouldRefreshUiLiveData.postValue(false); - // Clear queued tasks in handler. - DataLoaderThread.getHandler().removeCallbacksAndMessages(TOKEN); + clearQueuedTasksInDataLoaderThread(); initPhotoPickerData(); @@ -392,8 +418,8 @@ public class PickerViewModel extends AndroidViewModel { // number of items. This will be equal to page size for pagination if cloud // picker feature flag is enabled, else it will be -1 implying that the complete // list should be loaded. - updatePaginatedItems(new PaginationParameters(mItemsPageSize, -1, - -1), /* isReset */ true, action); + updatePaginatedItems(new PaginationParameters(mItemsPageSize, + /*dateBeforeMs*/ Long.MIN_VALUE, /*rowId*/ -1), /* isReset */ true, action); break; } case ACTION_REFRESH_ITEMS: { @@ -438,9 +464,6 @@ public class PickerViewModel extends AndroidViewModel { final UserId userId = mUserIdManager.getCurrentUserProfileId(); DataLoaderThread.getHandler().postDelayed(() -> { - if (action == ACTION_LOAD_NEXT_PAGE && mIsAllItemsLoaded) { - return; - } // Load the items as per the pagination parameters passed as params to this method. List<Item> newPageItemList = loadItems(Category.DEFAULT, userId, pagingParameters); @@ -451,13 +474,8 @@ public class PickerViewModel extends AndroidViewModel { mItemsResult.getValue() == null || isReset ? new ArrayList<>() : mItemsResult.getValue().getItems(); updatedList.addAll(newPageItemList); - - if (isReset) { - mIsAllItemsLoaded = false; - } Log.d(TAG, "Next page for photos items have been loaded."); if (newPageItemList.isEmpty()) { - mIsAllItemsLoaded = true; Log.d(TAG, "All photos items have been loaded."); } @@ -525,7 +543,10 @@ public class PickerViewModel extends AndroidViewModel { switch (action) { case ACTION_VIEW_CREATED: { // This call is made only for loading the first page of album media, - // hence the category and category item list should be refreshed each time. + // so the existing data loader thread tasks for updating the category items should + // be cleared and the category and category item list should be refreshed each time. + DataLoaderThread.getHandler().removeCallbacksAndMessages( + mLoadCategoryItemsThreadToken); mCategoryItemsResult = new MutableLiveData<>(); mCurrentCategory = category; assert paginationParameters != null; @@ -588,13 +609,14 @@ public class PickerViewModel extends AndroidViewModel { private void loadCategoryItemsAsync(PaginationParameters pagingParameters, boolean isReset, @ItemsAction.Type int action) { final UserId userId = mUserIdManager.getCurrentUserProfileId(); + final Category category = mCurrentCategory; DataLoaderThread.getHandler().postDelayed(() -> { if (action == ACTION_LOAD_NEXT_PAGE && mIsAllCategoryItemsLoaded) { return; } // Load the items as per the pagination parameters passed as params to this method. - List<Item> newPageItemList = loadItems(mCurrentCategory, userId, pagingParameters); + List<Item> newPageItemList = loadItems(category, userId, pagingParameters); // Based on if it is a reset case or not, create an updated list. // If it is a reset case, assign an empty list else use the contents of the pre-existing @@ -607,13 +629,15 @@ public class PickerViewModel extends AndroidViewModel { mIsAllCategoryItemsLoaded = false; } Log.d(TAG, "Next page for category items have been loaded. Category: " - + mCurrentCategory + " " + updatedList.size()); + + category + " " + updatedList.size()); if (newPageItemList.isEmpty()) { mIsAllCategoryItemsLoaded = true; Log.d(TAG, "All items have been loaded for category: " + mCurrentCategory); } - mCategoryItemsResult.postValue(new PaginatedItemsResult(updatedList, action)); - }, TOKEN, DELAY_MILLIS); + if (Objects.equals(category, mCurrentCategory)) { + mCategoryItemsResult.postValue(new PaginatedItemsResult(updatedList, action)); + } + }, mLoadCategoryItemsThreadToken, DELAY_MILLIS); } /** @@ -799,8 +823,6 @@ public class PickerViewModel extends AndroidViewModel { maybeLogPickerOpenedWithCloudProvider(); } - // TODO(b/245745412): Fix log params (uid & package name) - // TODO(b/245745424): Solve for active cloud provider without a logged in account private void maybeLogPickerOpenedWithCloudProvider() { if (shouldShowOnlyLocalFeatures()) { return; @@ -815,8 +837,8 @@ public class PickerViewModel extends AndroidViewModel { + ", log=" + (providerAuthority != null)); if (providerAuthority != null) { - mLogger.logPickerOpenWithActiveCloudProvider( - mInstanceId, /* cloudProviderUid */ -1, providerAuthority); + BackgroundThread.getExecutor().execute(() -> + logPickerOpenedWithCloudProvider(providerAuthority)); } // We only need to get the value once. cloudMediaProviderAuthorityLiveData.removeObserver(this); @@ -824,6 +846,27 @@ public class PickerViewModel extends AndroidViewModel { }); } + private void logPickerOpenedWithCloudProvider(@NonNull String providerAuthority) { + String cloudProviderPackage = providerAuthority; + int cloudProviderUid = -1; + + try { + final PackageManager packageManager = + UserId.CURRENT_USER.getPackageManager(mAppContext); + final ProviderInfo providerInfo = packageManager.resolveContentProvider( + providerAuthority, /* flags= */ 0); + + cloudProviderPackage = providerInfo.applicationInfo.packageName; + cloudProviderUid = providerInfo.applicationInfo.uid; + } catch (PackageManager.NameNotFoundException e) { + Log.d(TAG, "Logging the ui event 'picker open with an active cloud provider' with its " + + "authority in place of the package name and a default uid.", e); + } + + mLogger.logPickerOpenWithActiveCloudProvider( + mInstanceId, cloudProviderUid, cloudProviderPackage); + } + /** * Log metrics to notify that the user has clicked Browse to open DocumentsUi */ @@ -1209,4 +1252,9 @@ public class PickerViewModel extends AndroidViewModel { }, TOKEN, DELAY_MILLIS); } } + + private void clearQueuedTasksInDataLoaderThread() { + DataLoaderThread.getHandler().removeCallbacksAndMessages(TOKEN); + DataLoaderThread.getHandler().removeCallbacksAndMessages(mLoadCategoryItemsThreadToken); + } } diff --git a/src/com/android/providers/media/stableuris/dao/BackupIdRow.java b/src/com/android/providers/media/stableuris/dao/BackupIdRow.java index 27060d5d7..0bd03906d 100644 --- a/src/com/android/providers/media/stableuris/dao/BackupIdRow.java +++ b/src/com/android/providers/media/stableuris/dao/BackupIdRow.java @@ -20,13 +20,8 @@ import android.provider.MediaStore.MediaColumns; import com.android.providers.media.util.StringUtils; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.Base64; import java.util.Objects; /** @@ -248,24 +243,35 @@ public final class BackupIdRow implements Serializable { /** * Serializes the given {@link BackupIdRow} object to a string + * Format is + * "is_dirty::_id::is_fav::is_pending::is_trashed::media_type::user_id::owner_id::date_expires" */ public static String serialize(BackupIdRow backupIdRow) throws IOException { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); - objectOutputStream.writeObject(backupIdRow); - objectOutputStream.close(); - return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()); + return String.format("%s::%s::%s::%s::%s::%s::%s::%s::%s", + backupIdRow.getIsDirty() ? "1" : "0", backupIdRow.getId(), + backupIdRow.getIsFavorite(), backupIdRow.getIsPending(), backupIdRow.getIsTrashed(), + backupIdRow.getMediaType(), backupIdRow.getUserId(), + backupIdRow.getOwnerPackageId(), backupIdRow.getDateExpires()); } /** * Deserializes the given string to {@link BackupIdRow} object */ public static BackupIdRow deserialize(String s) throws IOException, ClassNotFoundException { - byte[] bytes = Base64.getDecoder().decode(s); - ObjectInputStream objectInputStream = new ObjectInputStream( - new ByteArrayInputStream(bytes)); - BackupIdRow backupIdRow = (BackupIdRow) objectInputStream.readObject(); - objectInputStream.close(); - return backupIdRow; + if (s == null || s.isEmpty()) { + return null; + } + + String[] fields = s.split("::"); + BackupIdRow.Builder builder = BackupIdRow.newBuilder(Long.parseLong(fields[1])); + builder.setIsDirty(Objects.equals(fields[0], "1")); + builder.setIsFavorite(Integer.parseInt(fields[2])); + builder.setIsPending(Integer.parseInt(fields[3])); + builder.setIsTrashed(Integer.parseInt(fields[4])); + builder.setMediaType(Integer.parseInt(fields[5])); + builder.setUserId(Integer.parseInt(fields[6])); + builder.setOwnerPackagedId(Integer.parseInt(fields[7])); + builder.setDateExpires(fields[8]); + return builder.build(); } } diff --git a/tests/Android.bp b/tests/Android.bp index 2bb5f3766..4dbaf16e7 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -229,3 +229,10 @@ filegroup { name: "mediaprovider-testutils", srcs: ["utils/**/*.java"], } + +filegroup { + name: "mediaprovider-library", + srcs: [ + "src/com/android/providers/media/library/RunOnlyOnPostsubmit.java", + ], +} diff --git a/tests/client/Android.bp b/tests/client/Android.bp index 7e5182870..ca3687d7c 100644 --- a/tests/client/Android.bp +++ b/tests/client/Android.bp @@ -16,6 +16,7 @@ android_test { srcs: [ "src/**/*.java", ":mediaprovider-testutils", + ":mediaprovider-library", ], libs: [ diff --git a/tests/client/src/com/android/providers/media/client/ClientPlaylistTest.java b/tests/client/src/com/android/providers/media/client/ClientPlaylistTest.java index e9b9cbf26..dc86aae55 100644 --- a/tests/client/src/com/android/providers/media/client/ClientPlaylistTest.java +++ b/tests/client/src/com/android/providers/media/client/ClientPlaylistTest.java @@ -41,6 +41,8 @@ import android.util.Pair; import androidx.test.InstrumentationRegistry; +import com.android.providers.media.library.RunOnlyOnPostsubmit; + import org.junit.After; import org.junit.Assume; import org.junit.Before; @@ -63,6 +65,7 @@ import java.util.concurrent.TimeUnit; * external client app. Exercises all supported playlist formats. */ @RunWith(Parameterized.class) +@RunOnlyOnPostsubmit public class ClientPlaylistTest { private static final String TAG = "ClientPlaylistTest"; diff --git a/tests/client/src/com/android/providers/media/client/PerformanceTest.java b/tests/client/src/com/android/providers/media/client/PerformanceTest.java index b792ee22c..f7f5c27ad 100644 --- a/tests/client/src/com/android/providers/media/client/PerformanceTest.java +++ b/tests/client/src/com/android/providers/media/client/PerformanceTest.java @@ -36,6 +36,7 @@ import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.UiDevice; +import com.android.providers.media.library.RunOnlyOnPostsubmit; import com.android.providers.media.tests.utils.Timer; import org.junit.Test; @@ -62,6 +63,7 @@ import java.util.concurrent.TimeUnit; */ @RunWith(AndroidJUnit4.class) @LargeTest +@RunOnlyOnPostsubmit public class PerformanceTest { private static final String TAG = "PerformanceTest"; diff --git a/tests/client/src/com/android/providers/media/client/PlaylistPerformanceTest.java b/tests/client/src/com/android/providers/media/client/PlaylistPerformanceTest.java index e76181420..c7739785d 100644 --- a/tests/client/src/com/android/providers/media/client/PlaylistPerformanceTest.java +++ b/tests/client/src/com/android/providers/media/client/PlaylistPerformanceTest.java @@ -37,6 +37,7 @@ import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.providers.media.library.RunOnlyOnPostsubmit; import com.android.providers.media.tests.utils.Timer; import org.junit.After; @@ -49,6 +50,7 @@ import java.io.IOException; import java.io.OutputStream; @RunWith(AndroidJUnit4.class) +@RunOnlyOnPostsubmit public class PlaylistPerformanceTest { private static final Uri AUDIO_URI = MediaStore.Audio.Media .getContentUri(VOLUME_EXTERNAL_PRIMARY); diff --git a/tests/client/src/com/android/providers/media/client/PublicVolumePlaylistTest.java b/tests/client/src/com/android/providers/media/client/PublicVolumePlaylistTest.java index af17d50c9..6f0d33dd4 100644 --- a/tests/client/src/com/android/providers/media/client/PublicVolumePlaylistTest.java +++ b/tests/client/src/com/android/providers/media/client/PublicVolumePlaylistTest.java @@ -40,6 +40,8 @@ import android.provider.MediaStore; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.providers.media.library.RunOnlyOnPostsubmit; + import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; @@ -49,6 +51,7 @@ import org.junit.runner.RunWith; import java.io.OutputStream; @RunWith(AndroidJUnit4.class) +@RunOnlyOnPostsubmit public class PublicVolumePlaylistTest { @BeforeClass public static void setUp() throws Exception { diff --git a/tests/client/src/com/android/providers/media/client/PublicVolumeTest.java b/tests/client/src/com/android/providers/media/client/PublicVolumeTest.java index e5181d5b0..da80f4181 100644 --- a/tests/client/src/com/android/providers/media/client/PublicVolumeTest.java +++ b/tests/client/src/com/android/providers/media/client/PublicVolumeTest.java @@ -36,6 +36,8 @@ import android.provider.MediaStore; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.providers.media.library.RunOnlyOnPostsubmit; + import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; @@ -45,6 +47,7 @@ import org.junit.runner.RunWith; import java.io.OutputStream; @RunWith(AndroidJUnit4.class) +@RunOnlyOnPostsubmit public class PublicVolumeTest { @BeforeClass public static void setUp() throws Exception { diff --git a/tests/src/com/android/providers/media/DatabaseBackupAndRecoveryTest.java b/tests/src/com/android/providers/media/DatabaseBackupAndRecoveryTest.java index 6b459933b..447a98fa0 100644 --- a/tests/src/com/android/providers/media/DatabaseBackupAndRecoveryTest.java +++ b/tests/src/com/android/providers/media/DatabaseBackupAndRecoveryTest.java @@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertTrue; import android.content.Context; +import android.os.UserHandle; import androidx.test.core.app.ApplicationProvider; import androidx.test.runner.AndroidJUnit4; @@ -77,4 +78,16 @@ public class DatabaseBackupAndRecoveryTest { assertThat(DatabaseBackupAndRecovery.getInvalidUsersList(xattrData, /* validUserIds */ Arrays.asList("0", "13"))).containsExactly("10", "11", "12"); } + + @Test + public void testGetFilePathForFuseRequests() { + assertThat(DatabaseBackupAndRecovery.getFilePathForFuseRequests("/storage")).isEqualTo( + "/storage/emulated/" + UserHandle.myUserId()); + assertThat(DatabaseBackupAndRecovery.getFilePathForFuseRequests( + "/storage/emulated/" + UserHandle.myUserId() + "/Android/media")).isEqualTo( + "/storage/emulated/" + UserHandle.myUserId()); + assertThat( + DatabaseBackupAndRecovery.getFilePathForFuseRequests("/storage/ABC-DEF")).isEqualTo( + "/storage/ABC-DEF"); + } } diff --git a/tests/src/com/android/providers/media/IsolatedContext.java b/tests/src/com/android/providers/media/IsolatedContext.java index 8a87eb5ad..dc52fcd3d 100644 --- a/tests/src/com/android/providers/media/IsolatedContext.java +++ b/tests/src/com/android/providers/media/IsolatedContext.java @@ -31,8 +31,10 @@ import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import com.android.providers.media.cloudproviders.CloudProviderPrimary; +import com.android.providers.media.cloudproviders.FlakyCloudProvider; import com.android.providers.media.photopicker.PhotoPickerProvider; import com.android.providers.media.photopicker.PickerSyncController; import com.android.providers.media.util.FileUtils; @@ -48,6 +50,7 @@ public class IsolatedContext extends ContextWrapper { private final MockContentResolver mResolver; private final MediaProvider mMediaProvider; private final UserHandle mUserHandle; + private final FlakyCloudProvider mFlakyCloudProvider; public IsolatedContext(Context base, String tag, boolean asFuseThread) { this(base, tag, asFuseThread, base.getUser()); @@ -88,6 +91,9 @@ public class IsolatedContext extends ContextWrapper { final CloudMediaProvider cmp = new CloudProviderPrimary(); attachInfoAndAddProvider(base, cmp, CloudProviderPrimary.AUTHORITY); + mFlakyCloudProvider = new FlakyCloudProvider(); + attachInfoAndAddProvider(base, mFlakyCloudProvider, FlakyCloudProvider.AUTHORITY); + MediaStore.waitForIdle(mResolver); } @@ -162,4 +168,13 @@ public class IsolatedContext extends ContextWrapper { } } + @VisibleForTesting + public void setFlakyCloudProviderToFlakeInTheNextRequest() { + mFlakyCloudProvider.setToFlakeInTheNextRequest(); + } + + @VisibleForTesting + public void resetFlakyCloudProviderToNotFlakeInTheNextRequest() { + mFlakyCloudProvider.resetToNotFlakeInTheNextRequest(); + } } diff --git a/tests/src/com/android/providers/media/MediaGrantsTest.java b/tests/src/com/android/providers/media/MediaGrantsTest.java index aae4f8454..66346fbfb 100644 --- a/tests/src/com/android/providers/media/MediaGrantsTest.java +++ b/tests/src/com/android/providers/media/MediaGrantsTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import android.Manifest; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.Context; import android.database.Cursor; import android.net.Uri; @@ -51,6 +52,7 @@ public class MediaGrantsTest { private MediaGrants mGrants; private static final String TEST_OWNER_PACKAGE_NAME = "com.android.test.package"; + private static final String TEST_OWNER_PACKAGE_NAME2 = "com.android.test.package2"; private static final int TEST_USER_ID = UserHandle.myUserId(); @BeforeClass @@ -96,6 +98,46 @@ public class MediaGrantsTest { } @Test + public void testGetMediaGrantsForPackage() throws Exception { + Long fileId1 = insertFileInResolver(mIsolatedResolver, "test_file1"); + Long fileId2 = insertFileInResolver(mIsolatedResolver, "test_file2"); + Long fileId3 = insertFileInResolver(mIsolatedResolver, "test_file3"); + List<Uri> uris1 = List.of(buildValidPickerUri(fileId1), buildValidPickerUri(fileId2)); + List<Uri> uris2 = List.of(buildValidPickerUri(fileId3)); + + mGrants.addMediaGrantsForPackage(TEST_OWNER_PACKAGE_NAME, uris1, TEST_USER_ID); + mGrants.addMediaGrantsForPackage(TEST_OWNER_PACKAGE_NAME2, uris2, TEST_USER_ID); + + + List<Uri> fileUris = mGrants.getMediaGrantsForPackage( + TEST_OWNER_PACKAGE_NAME, TEST_USER_ID); + + List<Long> expectedFileIdsList = List.of(fileId1, fileId2); + + assertEquals(fileUris.size(), expectedFileIdsList.size()); + for (Uri uri: fileUris) { + assertTrue(expectedFileIdsList.contains(Long.valueOf(ContentUris.parseId(uri)))); + } + + List<Uri> fileUrisForTestPackage2 = mGrants.getMediaGrantsForPackage( + TEST_OWNER_PACKAGE_NAME2, TEST_USER_ID); + + List<Long> expectedFileIdsList2 = List.of(fileId3); + + assertEquals(fileUrisForTestPackage2.size(), expectedFileIdsList2.size()); + for (Uri uri: fileUrisForTestPackage2) { + assertTrue(expectedFileIdsList2.contains(Long.valueOf(ContentUris.parseId(uri)))); + } + + List<Uri> fileUrisForTestPackage3 = mGrants.getMediaGrantsForPackage( + "non.existent.package", TEST_USER_ID); + + // assert no items are returned for an invalid package. + assertEquals(/* expected= */fileUrisForTestPackage3.size(), /* actual= */0); + + } + + @Test public void testAddDuplicateMediaGrants() throws Exception { Long fileId1 = insertFileInResolver(mIsolatedResolver, "test_file1"); diff --git a/tests/src/com/android/providers/media/PublicVolumeTest.java b/tests/src/com/android/providers/media/PublicVolumeTest.java index e2a272f2b..aaed1f9de 100644 --- a/tests/src/com/android/providers/media/PublicVolumeTest.java +++ b/tests/src/com/android/providers/media/PublicVolumeTest.java @@ -30,6 +30,7 @@ import android.provider.MediaStore; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.providers.media.library.RunOnlyOnPostsubmit; import com.android.providers.media.tests.utils.PublicVolumeSetupHelper; import com.android.providers.media.util.FileUtils; @@ -43,6 +44,7 @@ import java.io.File; import java.util.List; @RunWith(AndroidJUnit4.class) +@RunOnlyOnPostsubmit public class PublicVolumeTest { static final int POLL_DELAY_MS = 500; static final int WAIT_FOR_DEFAULT_FOLDERS_MS = 30000; diff --git a/tests/src/com/android/providers/media/TestConfigStore.java b/tests/src/com/android/providers/media/TestConfigStore.java index 038be6269..a19360320 100644 --- a/tests/src/com/android/providers/media/TestConfigStore.java +++ b/tests/src/com/android/providers/media/TestConfigStore.java @@ -18,9 +18,12 @@ package com.android.providers.media; import static java.util.Objects.requireNonNull; +import android.util.Pair; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -32,36 +35,49 @@ import java.util.concurrent.Executor; */ public class TestConfigStore implements ConfigStore { private boolean mCloudMediaInPhotoPickerEnabled = false; - private @Nullable List<String> mAllowedCloudProviderPackages = null; + private List<String> mAllowedCloudProviderPackages = Collections.emptyList(); private @Nullable String mDefaultCloudProviderPackage = null; + private List<Pair<Executor, Runnable>> mObservers = new ArrayList<>(); public void enableCloudMediaFeatureAndSetAllowedCloudProviderPackages(String... providers) { mAllowedCloudProviderPackages = Arrays.asList(providers); - enableCloudMediaFeature(); + mCloudMediaInPhotoPickerEnabled = true; + notifyObservers(); } public void enableCloudMediaFeature() { mCloudMediaInPhotoPickerEnabled = true; + notifyObservers(); } public void clearAllowedCloudProviderPackagesAndDisableCloudMediaFeature() { - mAllowedCloudProviderPackages = null; + mAllowedCloudProviderPackages = Collections.emptyList(); disableCloudMediaFeature(); + notifyObservers(); } public void disableCloudMediaFeature() { mCloudMediaInPhotoPickerEnabled = false; + notifyObservers(); } @Override public @NonNull List<String> getAllowedCloudProviderPackages() { - return mAllowedCloudProviderPackages != null ? mAllowedCloudProviderPackages - : Collections.emptyList(); + return mAllowedCloudProviderPackages; + } + + public void setAllowedCloudProviderPackages(String... providers) { + if (providers.length == 0) { + mAllowedCloudProviderPackages = Collections.emptyList(); + } else { + mAllowedCloudProviderPackages = Arrays.asList(providers); + } + notifyObservers(); } @Override public boolean isCloudMediaInPhotoPickerEnabled() { - return mCloudMediaInPhotoPickerEnabled; + return mCloudMediaInPhotoPickerEnabled && !mAllowedCloudProviderPackages.isEmpty(); } public void setDefaultCloudProviderPackage(@NonNull String packageName) { @@ -94,6 +110,19 @@ public class TestConfigStore implements ConfigStore { @Override public void addOnChangeListener(@NonNull Executor executor, @NonNull Runnable listener) { - // No-op. + Pair p = Pair.create(executor, listener); + mObservers.add(p); + } + + + /** + * Runs all subscribers to the TestConfigStore. + */ + private void notifyObservers() { + for (Pair<Executor, Runnable> observer: mObservers) { + Executor exec = observer.first; + Runnable listener = observer.second; + exec.execute(listener); + } } } diff --git a/tests/src/com/android/providers/media/TestDatabaseBackupAndRecovery.java b/tests/src/com/android/providers/media/TestDatabaseBackupAndRecovery.java index 63af35780..fc2dc77a4 100644 --- a/tests/src/com/android/providers/media/TestDatabaseBackupAndRecovery.java +++ b/tests/src/com/android/providers/media/TestDatabaseBackupAndRecovery.java @@ -75,7 +75,7 @@ public class TestDatabaseBackupAndRecovery extends DatabaseBackupAndRecovery { } @Override - protected FuseDaemon getFuseDaemonForFileWithWait(File fuseFilePath, long waitTime) + protected FuseDaemon getFuseDaemonForFileWithWait(File fuseFilePath) throws FileNotFoundException { return null; } diff --git a/tests/src/com/android/providers/media/cloudproviders/CloudProviderSecondary.java b/tests/src/com/android/providers/media/cloudproviders/CloudProviderSecondary.java index ac7cef0d5..5c3df94d8 100644 --- a/tests/src/com/android/providers/media/cloudproviders/CloudProviderSecondary.java +++ b/tests/src/com/android/providers/media/cloudproviders/CloudProviderSecondary.java @@ -38,7 +38,7 @@ import java.io.FileNotFoundException; * {@link MediaGenerator} */ public class CloudProviderSecondary extends CloudMediaProvider { - private static final String AUTHORITY = + public static final String AUTHORITY = "com.android.providers.media.photopicker.tests.cloud_secondary"; private final MediaGenerator mMediaGenerator = diff --git a/tests/src/com/android/providers/media/cloudproviders/FlakyCloudProvider.java b/tests/src/com/android/providers/media/cloudproviders/FlakyCloudProvider.java index d4c3dec30..2d20574b8 100644 --- a/tests/src/com/android/providers/media/cloudproviders/FlakyCloudProvider.java +++ b/tests/src/com/android/providers/media/cloudproviders/FlakyCloudProvider.java @@ -20,6 +20,8 @@ import static android.provider.CloudMediaProviderContract.EXTRA_PAGE_TOKEN; import static com.android.providers.media.PickerProviderMediaGenerator.MediaGenerator; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.graphics.Point; @@ -27,6 +29,9 @@ import android.os.Bundle; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.provider.CloudMediaProvider; +import android.util.Log; + +import androidx.annotation.VisibleForTesting; import com.android.providers.media.PickerProviderMediaGenerator; import com.android.providers.media.photopicker.data.CloudProviderQueryExtras; @@ -41,24 +46,28 @@ import java.io.FileNotFoundException; * out of every three requests. */ public class FlakyCloudProvider extends CloudMediaProvider { + private static final String TAG = "FlakyCloudProvider"; public static final String AUTHORITY = "com.android.providers.media.photopicker.tests.cloud_flaky"; + public static final String ACCOUNT_NAME = "test_account@flakyCloudProvider"; + private static final int INITIAL_REQUEST_COUNT = 0; + private static final int REQUEST_COUNT_FOR_NEXT_ONE_TO_FLAKE = 2; private final MediaGenerator mMediaGenerator = PickerProviderMediaGenerator.getMediaGenerator(AUTHORITY); - private int mRequestCount = 0; + private int mRequestCount = INITIAL_REQUEST_COUNT; /** Determines if the current request should flake. */ private boolean shouldFlake() { // Always succeed on the first request. - if (++mRequestCount < 2) { + if (++mRequestCount < REQUEST_COUNT_FOR_NEXT_ONE_TO_FLAKE) { return false; } - if (mRequestCount >= 3) { - mRequestCount = 0; + if (mRequestCount > REQUEST_COUNT_FOR_NEXT_ONE_TO_FLAKE) { + mRequestCount = INITIAL_REQUEST_COUNT; } return true; @@ -66,6 +75,7 @@ public class FlakyCloudProvider extends CloudMediaProvider { @Override public boolean onCreate() { + mMediaGenerator.setAccountInfo(ACCOUNT_NAME, /* configIntent= */ null); return true; } @@ -137,6 +147,24 @@ public class FlakyCloudProvider extends CloudMediaProvider { @Override public Bundle onGetMediaCollectionInfo(Bundle extras) { + if (shouldFlake()) { + try { + MILLISECONDS.sleep(/* timeout= */ 200L); + } catch (InterruptedException e) { + Log.d(TAG, "Error while sleep when should flake on get media collection info.", e); + } + } + return mMediaGenerator.getMediaCollectionInfo(); } + + @VisibleForTesting + public void resetToNotFlakeInTheNextRequest() { + mRequestCount = INITIAL_REQUEST_COUNT; + } + + @VisibleForTesting + public void setToFlakeInTheNextRequest() { + mRequestCount = REQUEST_COUNT_FOR_NEXT_ONE_TO_FLAKE; + } } diff --git a/tests/src/com/android/providers/media/photopicker/ItemsProviderTest.java b/tests/src/com/android/providers/media/photopicker/ItemsProviderTest.java index 1dd565b9e..5de28d31a 100644 --- a/tests/src/com/android/providers/media/photopicker/ItemsProviderTest.java +++ b/tests/src/com/android/providers/media/photopicker/ItemsProviderTest.java @@ -32,12 +32,14 @@ import static com.android.providers.media.util.MimeUtils.isVideoMimeType; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.Manifest; import android.app.Instrumentation; import android.app.UiAutomation; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.res.AssetFileDescriptor; @@ -81,6 +83,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Consumer; +import java.util.stream.Collectors; public class ItemsProviderTest { /** @@ -662,7 +665,7 @@ public class ItemsProviderTest { try { // Set the limit and ensure that only that number of items are returned. final Cursor res = mItemsProvider.getAllItems(Category.DEFAULT, - new PaginationParameters(/* limit */ 5, -1, -1), + new PaginationParameters(/* limit */ 5, /*dateBeforeMs*/ Long.MIN_VALUE, -1), /* mimeType */ null, /* userId */ null, /* cancellationSignal */ null); assertThat(res).isNotNull(); @@ -961,6 +964,72 @@ public class ItemsProviderTest { } /** + * Tests {@link ItemsProvider#getLocalItemsForSelection(Category, List, String[], + * UserId, CancellationSignal)} to return only selected items from the media table for ids + * defined in the localId selection list. + */ + @Test + public void testGetItemsImages_withLocalIdSelection() throws Exception { + List<Uri> imageFilesUris = assertCreateNewImagesWithSameDateModifiedTimesAndReturnUri(10); + // Put the id of random items from the inserted set. say 4th and 6th item. + ArrayList<Long> inputIds = new ArrayList<>(1); + inputIds.add(ContentUris.parseId(imageFilesUris.get(4))); + inputIds.add(ContentUris.parseId(imageFilesUris.get(6))); + ArrayList<Integer> inputIdsAsIntegers = + (ArrayList<Integer>) inputIds.stream().map( + (Long id) -> Integer.valueOf(Math.toIntExact(id))).collect( + Collectors.toList()); + try { + // get the item objects for the provided ids. + final Cursor res = mItemsProvider.getLocalItemsForSelection(Category.DEFAULT, + /* local id selection list */ inputIdsAsIntegers, + /* mimeType */ new String[]{"image/*"}, /* userId */ null, + /* cancellationSignal */ null); + + // verify that the correct number of items are returned and that they have the correct + // ids. + assertThat(res).isNotNull(); + assertThat(res.getCount()).isEqualTo(2); + res.moveToPosition(0); + while (res.moveToNext()) { + Item item = Item.fromCursor(res, UserId.CURRENT_USER); + assertTrue(inputIds.contains(Long.parseLong(item.getId()))); + } + assertThatOnlyImages(res); + } finally { + // clean up. + deleteAllFilesNoThrow(); + } + } + + /** + * Tests {@link ItemsProvider#getLocalItemsForSelection(Category, List, String[], + * UserId, CancellationSignal)} to return only selected items from the media table for ids + * defined in the localId selection list. Here the list is empty so the parameter is ignored and + * the list is returned without any selection. + */ + @Test + public void testGetItemsImages_withLocalIdSelectionEmpty() throws Exception { + assertCreateNewImagesWithSameDateModifiedTimesAndReturnUri(10); + try { + // get the item objects for the empty list. + final Cursor res = mItemsProvider.getLocalItemsForSelection(Category.DEFAULT, + /* local id selection list */ new ArrayList<>(), + /* mimeType */ new String[]{"image/*"}, /* userId */ null, + /* cancellationSignal */ null); + + assertThat(res).isNotNull(); + // All images are returned and selection is ignored. + assertThat(res.getCount()).isEqualTo(10); + assertThatOnlyImages(res); + } finally { + // clean up. + deleteAllFilesNoThrow(); + } + } + + + /** * Tests * {@link ItemsProvider#getAllItems(Category, PaginationParameters, String[], UserId)} * (Category, PaginationParameters, String[], UserId)} (Category, int, String[], UserId)} @@ -1172,6 +1241,7 @@ public class ItemsProviderTest { try (Cursor c = mItemsProvider.getAllCategories(/* mimeType */ null, /* userId */ null, /* cancellationSignal*/ null)) { assertGetCategoriesMatchMultiple(c, Arrays.asList( + Pair.create(ALBUM_ID_FAVORITES, 0), Pair.create(ALBUM_ID_VIDEOS, 2), Pair.create(ALBUM_ID_SCREENSHOTS, 1), Pair.create(cloudAlbum, 1) @@ -1404,6 +1474,19 @@ public class ItemsProviderTest { return imageFiles; } + + private List<Uri> assertCreateNewImagesWithSameDateModifiedTimesAndReturnUri(int numberOfImages) + throws Exception { + List<Uri> imageFiles = new ArrayList<>(); + long currentTime = System.nanoTime() / 1000; + for (int itr = 0; itr < numberOfImages; itr++) { + String fileName = TAG + "_file_" + String.valueOf(System.nanoTime()) + ".jpg"; + imageFiles.add(assertCreateNewFileWithLastModifiedTimeAndReturnUri( + getDownloadsDir(), fileName, currentTime)); + } + return imageFiles; + } + private File assertCreateNewVideo(File dir) throws Exception { return assertCreateNewFile(dir, VIDEO_FILE_NAME); } @@ -1433,6 +1516,11 @@ public class ItemsProviderTest { prepareFileAndGetUri(file, lastModifiedTime); return file; } + private Uri assertCreateNewFileWithLastModifiedTimeAndReturnUri(File parentDir, String fileName, + long lastModifiedTime) throws Exception { + final File file = new File(parentDir, fileName); + return prepareFileAndGetUri(file, lastModifiedTime); + } private Uri prepareFileAndGetUri(File file, long lastModifiedTime) throws IOException { diff --git a/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java b/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java index a8d3dd4fc..8395b1bd9 100644 --- a/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java +++ b/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java @@ -22,11 +22,15 @@ import static android.provider.CloudMediaProviderContract.AlbumColumns.ALBUM_ID_ import static com.android.providers.media.PickerProviderMediaGenerator.MediaGenerator; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.LONG_DEFAULT; import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.STRING_DEFAULT; +import static com.android.providers.media.photopicker.sync.SyncWorkerTestUtils.initializeTestWorkManager; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import android.content.Context; import android.content.Intent; @@ -40,13 +44,17 @@ import android.util.Pair; import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import androidx.work.WorkManager; import com.android.modules.utils.BackgroundThread; import com.android.providers.media.PickerProviderMediaGenerator; import com.android.providers.media.TestConfigStore; +import com.android.providers.media.photopicker.data.CloudProviderInfo; import com.android.providers.media.photopicker.data.PickerDatabaseHelper; import com.android.providers.media.photopicker.data.PickerDbFacade; import com.android.providers.media.photopicker.data.PickerSyncRequestExtras; +import com.android.providers.media.photopicker.sync.PickerSyncManager; +import com.android.providers.media.util.ForegroundThread; import org.junit.After; import org.junit.Before; @@ -55,8 +63,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; @RunWith(AndroidJUnit4.class) public class PickerDataLayerTest { @@ -108,6 +119,7 @@ public class PickerDataLayerTest { private PickerDbFacade mFacade; private PickerDataLayer mDataLayer; private PickerSyncController mController; + private TestConfigStore mConfigStore; @Before public void setUp() { @@ -128,13 +140,17 @@ public class PickerDataLayerTest { mDbHelper = new PickerDatabaseHelper(mContext, DB_NAME, DB_VERSION_1); mFacade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY, mDbHelper); - final TestConfigStore configStore = new TestConfigStore(); - configStore.enableCloudMediaFeatureAndSetAllowedCloudProviderPackages(PACKAGE_NAME); + mConfigStore = new TestConfigStore(); + mConfigStore.enableCloudMediaFeatureAndSetAllowedCloudProviderPackages(PACKAGE_NAME); mController = PickerSyncController.initialize( - mContext, mFacade, configStore, LOCAL_PROVIDER_AUTHORITY); - mDataLayer = new PickerDataLayer(mContext, mFacade, mController, configStore, - /* schedulePeriodicSyncs */ false); + mContext, mFacade, mConfigStore, LOCAL_PROVIDER_AUTHORITY); + + initializeTestWorkManager(mContext); + final WorkManager workManager = WorkManager.getInstance(mContext); + final PickerSyncManager syncManager = new PickerSyncManager( + workManager, mContext, mConfigStore, /* schedulePeriodicSyncs */ false); + mDataLayer = new PickerDataLayer(mContext, mFacade, mController, mConfigStore, syncManager); // Set cloud provider to null to discard mFacade.setCloudProvider(null); @@ -703,6 +719,83 @@ public class PickerDataLayerTest { () -> mDataLayer.initMediaData(syncExtras)); } + @Test + public void testCloudPackageAllowlistListenerRemovesActiveThatIsNowInvalid() { + mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY); + assertThat(mController.getCurrentCloudProviderInfo().packageName).isEqualTo(PACKAGE_NAME); + + // Simulate a DeviceConfig change where the Allowlist is set to empty. + mConfigStore.setAllowedCloudProviderPackages(new String[] {}); + + + // The listener uses the ForegroundThread to run the listener, so wait for the + // ForegroundThread to complete. + ForegroundThread.waitForIdle(); + + assertThat(mController.getCurrentCloudProviderInfo()).isEqualTo(CloudProviderInfo.EMPTY); + } + + @Test + public void testCloudPackageAllowlistListenerDoesNotChangeAllowedProvider() { + mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY); + assertThat(mController.getCurrentCloudProviderInfo().packageName).isEqualTo(PACKAGE_NAME); + + // Simulate a DeviceConfig change where the Allowlist adds a new provider, but the current + // provider is still permitted. + final String newlyAddedProviderPackage = "com.hooli.super.awesome.cloud.provider"; + mConfigStore.setAllowedCloudProviderPackages( + new String[] {PACKAGE_NAME, newlyAddedProviderPackage}); + + // The listener uses the ForegroundThread to run the listener, so wait for the + // ForegroundThread to complete. + ForegroundThread.waitForIdle(); + + // Ensure nothing was changed. + assertThat(mController.getCurrentCloudProviderInfo().packageName).isEqualTo(PACKAGE_NAME); + } + + @Test + public void testWaitForSyncWhenSyncFutureIsComplete() + throws ExecutionException, InterruptedException { + final CompletableFuture<Void> completableFuture = new CompletableFuture<>(); + completableFuture.complete(null); + + final int inputRetryCount = 3; + assertThat(mDataLayer + .waitForSync(completableFuture, "work-name", inputRetryCount)) + .isEqualTo(inputRetryCount); + } + + @Test + public void testWaitForSyncWhenSyncFutureNeverCompletes() + throws ExecutionException, InterruptedException, TimeoutException { + final PickerSyncManager mockSyncManager = mock(PickerSyncManager.class); + final PickerDataLayer dataLayer = new PickerDataLayer(mContext, mFacade, mController, + mConfigStore, mockSyncManager); + final CompletableFuture<Void> completableFuture = new CompletableFuture<>(); + doReturn(true).when(mockSyncManager).isUniqueWorkPending(any()); + + final int inputRetryCount = 3; + assertThat(dataLayer + .waitForSync(completableFuture, "work-name", inputRetryCount)) + .isEqualTo(0); + } + + @Test + public void testWaitForSyncWhenWorkerFails() + throws ExecutionException, InterruptedException, TimeoutException { + final PickerSyncManager mockSyncManager = mock(PickerSyncManager.class); + final PickerDataLayer dataLayer = new PickerDataLayer(mContext, mFacade, mController, + mConfigStore, mockSyncManager); + final CompletableFuture<Void> completableFuture = new CompletableFuture<>(); + doReturn(false).when(mockSyncManager).isUniqueWorkPending(any()); + + final int inputRetryCount = 3; + assertThat(dataLayer + .waitForSync(completableFuture, "work-name", inputRetryCount)) + .isEqualTo(inputRetryCount); + } + private static void waitForIdle() { final CountDownLatch latch = new CountDownLatch(1); BackgroundThread.getExecutor().execute(() -> { diff --git a/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java b/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java index 4869b8a22..1ff22ce3b 100644 --- a/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java +++ b/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java @@ -22,8 +22,10 @@ import static com.android.providers.media.photopicker.NotificationContentObserve import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -185,6 +187,78 @@ public class PickerSyncControllerTest { } @Test + public void testInitCloudProviderOnDeviceConfigChange() { + + TestConfigStore configStore = new TestConfigStore(); + configStore.disableCloudMediaFeature(); + + PickerSyncController controller = + PickerSyncController.initialize(mContext, mFacade, configStore); + assertThat(controller.getCurrentCloudProviderInfo()).isEqualTo(CloudProviderInfo.EMPTY); + configStore.setDefaultCloudProviderPackage(PACKAGE_NAME); + configStore.enableCloudMediaFeatureAndSetAllowedCloudProviderPackages(PACKAGE_NAME); + waitForIdle(); + + // Ensure the cloud provider is set to something. (The test package name here actually + // has multiple cloud providers in it, so just ensure something got set.) + assertThat(controller.getCurrentCloudProviderInfo().authority).isNotNull(); + + configStore.clearAllowedCloudProviderPackagesAndDisableCloudMediaFeature(); + waitForIdle(); + + // Ensure the cloud provider is correctly nulled out when the config changes again. + assertThat(controller.getCurrentCloudProviderInfo().authority).isNull(); + } + + @Test + public void testSyncIsCancelledIfCloudProviderIsChanged() { + + PickerSyncController controller = spy(mController); + + // Ensure we return the appropriate authority until we actually enter the sync process, + // and then return a different authority than what the sync was started with to simulate + // a cloud provider changing. + doReturn(CLOUD_PRIMARY_PROVIDER_AUTHORITY, + CLOUD_SECONDARY_PROVIDER_AUTHORITY) + .when(controller) + .getCloudProvider(); + + // Add local only media, we expect these to be successfully sync'd from the local provider. + addMedia(mLocalMediaGenerator, LOCAL_ONLY_1); + addMedia(mLocalMediaGenerator, LOCAL_ONLY_2); + mLocalMediaGenerator.setNextCursorExtras( + /* queryCount */ 2, + /* mediaCollectionId */ COLLECTION_1, + /* honoredSyncGeneration */ true, + /* honoredAlbumId */ false, + /* honoredPageSize */ true); + + // Add cloud media, we should try to sync these, but not actually commit them since the + // cloud provider will be changed before the transaction can be committed. + addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1); + addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2); + mCloudPrimaryMediaGenerator.setNextCursorExtras( + /* queryCount */ 2, + /* mediaCollectionId */ COLLECTION_1, + /* honoredSyncGeneration */ true, + /* honoredAlbumId */ false, + /* honoredPageSize */ true); + + controller.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY); + controller.syncAllMedia(); + + // The cursor should only contain the items from the local provider. (Even though we've + // aded a total of 4 items to the linked providers.) + try (Cursor cr = queryMedia()) { + assertThat(cr.getCount()).isEqualTo(2); + + assertCursor(cr, LOCAL_ID_2, LOCAL_PROVIDER_AUTHORITY); + assertCursor(cr, LOCAL_ID_1, LOCAL_PROVIDER_AUTHORITY); + } + + } + + @Test public void testSyncAllMediaNoCloud() { // 1. Do nothing mController.syncAllMedia(); @@ -354,29 +428,6 @@ public class PickerSyncControllerTest { } @Test - public void testSyncAllMediaResetsAlbumMedia() { - // 1. Set primary cloud provider - setCloudProviderAndSyncAllMedia(CLOUD_PRIMARY_PROVIDER_AUTHORITY); - assertEmptyCursorFromAlbumMediaQuery(ALBUM_ID_1, false); - - // 2. Add album_media - addAlbumMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1.first, CLOUD_ONLY_1.second, - ALBUM_ID_1); - addAlbumMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2.first, CLOUD_ONLY_2.second, - ALBUM_ID_1); - mController.syncAlbumMedia(ALBUM_ID_1, false); - - // 3. Assert non-empty album_media - try (Cursor cr = queryAlbumMedia(ALBUM_ID_1, false)) { - assertThat(cr.getCount()).isEqualTo(2); - } - - // 4. Sync all media and assert empty album_media - mController.syncAllMedia(); - assertEmptyCursorFromAlbumMediaQuery(ALBUM_ID_1, false); - } - - @Test public void testSyncAllAlbumMediaCloudOnly() { // 1. Add media before setting primary cloud provider addAlbumMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1.first, CLOUD_ONLY_1.second, @@ -1245,7 +1296,7 @@ public class PickerSyncControllerTest { } @Test - public void testContentNotifications() throws Exception { + public void testContentAddNotifications() throws Exception { NotificationContentObserver observer = new NotificationContentObserver(null); observer.register(mContext.getContentResolver()); @@ -1280,6 +1331,36 @@ public class PickerSyncControllerTest { } @Test + public void testContentDeleteNotifications() throws Exception { + NotificationContentObserver observer = new NotificationContentObserver(null); + observer.register(mContext.getContentResolver()); + + setCloudProviderAndSyncAllMedia(CLOUD_PRIMARY_PROVIDER_AUTHORITY); + + CountDownLatch latch = new CountDownLatch(1); + NotificationContentObserver.ContentObserverCallback callback = + spy(new TestableContentObserverCallback(latch)); + observer.registerKeysToObserverCallback(Arrays.asList(MEDIA), callback); + + addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1); + mCloudPrimaryMediaGenerator.setMediaCollectionId(COLLECTION_1); + mController.syncAllMedia(); + latch.await(2, TimeUnit.SECONDS); + verify(callback).onNotificationReceived(any(), any()); + + latch = new CountDownLatch(1); + callback = spy(new TestableContentObserverCallback(latch)); + observer.registerKeysToObserverCallback(Arrays.asList(MEDIA), callback); + + deleteMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1); + mController.syncAllMedia(); + latch.await(2, TimeUnit.SECONDS); + verify(callback).onNotificationReceived(any(), any()); + + observer.unregister(mContext.getContentResolver()); + } + + @Test public void testRefreshUiNotifications() throws InterruptedException { final ContentResolver contentResolver = mContext.getContentResolver(); final TestContentObserver refreshUiNotificationObserver = new TestContentObserver(null); diff --git a/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java b/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java index f38afe83b..cff210b9c 100644 --- a/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java +++ b/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java @@ -24,6 +24,8 @@ import static com.android.providers.media.util.MimeUtils.getExtensionFromMimeTyp import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.doReturn; +import static org.mockito.MockitoAnnotations.initMocks; import android.content.ContentValues; import android.content.Context; @@ -39,13 +41,18 @@ import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.providers.media.ProjectionHelper; +import com.android.providers.media.photopicker.sync.SyncTracker; +import com.android.providers.media.photopicker.sync.SyncTrackerRegistry; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import java.io.File; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; @RunWith(AndroidJUnit4.class) public class PickerDbFacadeTest { @@ -86,14 +93,25 @@ public class PickerDbFacadeTest { private Context mContext; private ProjectionHelper mProjectionHelper; + @Mock + private SyncTracker mMockLocalSyncTracker; + @Mock + private SyncTracker mMockCloudSyncTracker; + @Before public void setUp() { + initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); File dbPath = mContext.getDatabasePath(PickerDatabaseHelper.PICKER_DATABASE_NAME); dbPath.delete(); mFacade = new PickerDbFacade(mContext, LOCAL_PROVIDER); mFacade.setCloudProvider(CLOUD_PROVIDER); mProjectionHelper = new ProjectionHelper(Column.class, ExportedSince.class); + + + // Inject mock trackers + SyncTrackerRegistry.setLocalSyncTracker(mMockLocalSyncTracker); + SyncTrackerRegistry.setCloudSyncTracker(mMockCloudSyncTracker); } @After @@ -101,6 +119,10 @@ public class PickerDbFacadeTest { if (mFacade != null) { mFacade.setCloudProvider(null); } + + // Reset mock trackers + SyncTrackerRegistry.setLocalSyncTracker(new SyncTracker()); + SyncTrackerRegistry.setCloudSyncTracker(new SyncTracker()); } @Test @@ -241,6 +263,33 @@ public class PickerDbFacadeTest { } @Test + public void testAddCloudAlbumMediaWhileCloudSyncIsRunning() { + + + doReturn(Collections.singletonList(new CompletableFuture<>())) + .when(mMockCloudSyncTracker) + .pendingSyncFutures(); + + Cursor cursor1 = getAlbumMediaCursor(/* local id */ null, CLOUD_ID, DATE_TAKEN_MS + 1); + + assertAddAlbumMediaOperation(CLOUD_PROVIDER, cursor1, 1, ALBUM_ID); + + try (Cursor cr = queryAlbumMedia(ALBUM_ID, false)) { + assertThat(cr.getCount()).isEqualTo(1); + cr.moveToFirst(); + assertCloudMediaCursor(cr, CLOUD_ID, DATE_TAKEN_MS + 1); + } + + // These files should also be in the media table since we're pretending that + // we have a cloud sync running. + try (Cursor cr = queryMediaAll()) { + assertThat(cr.getCount()).isEqualTo(1); + cr.moveToFirst(); + assertCloudMediaCursor(cr, CLOUD_ID, DATE_TAKEN_MS + 1); + } + } + + @Test public void testAddCloudAlbumMediaAvailableOnDevice() { // Add local row for a media item in media table. final Cursor localCursor = getLocalMediaCursor(LOCAL_ID, DATE_TAKEN_MS); @@ -463,6 +512,39 @@ public class PickerDbFacadeTest { } @Test + public void testRemoveMedia_withLatestDateTakenMillis() { + Cursor localCursor = getLocalMediaCursor(LOCAL_ID, DATE_TAKEN_MS); + Cursor cloudCursor1 = getCloudMediaCursor(CLOUD_ID, LOCAL_ID, DATE_TAKEN_MS + 1); + + assertAddMediaOperation(LOCAL_PROVIDER, localCursor, 1); + assertAddMediaOperation(CLOUD_PROVIDER, cloudCursor1, 1); + + try (Cursor cr = queryMediaAll()) { + assertThat(cr.getCount()).isEqualTo(1); + cr.moveToFirst(); + assertCloudMediaCursor(cr, LOCAL_ID, DATE_TAKEN_MS); + } + + try (PickerDbFacade.DbWriteOperation operation = + mFacade.beginRemoveMediaOperation(CLOUD_PROVIDER)) { + assertWriteOperation(operation, getDeletedMediaCursor(CLOUD_ID), /* writeCount */ 1); + assertThat(operation.getFirstDateTakenMillis()).isEqualTo(DATE_TAKEN_MS + 1); + operation.setSuccess(); + } + + try (PickerDbFacade.DbWriteOperation operation = + mFacade.beginRemoveMediaOperation(LOCAL_PROVIDER)) { + assertWriteOperation(operation, getDeletedMediaCursor(LOCAL_ID), /* writeCount */ 1); + assertThat(operation.getFirstDateTakenMillis()).isEqualTo(DATE_TAKEN_MS); + operation.setSuccess(); + } + + try (Cursor cr = queryMediaAll()) { + assertThat(cr.getCount()).isEqualTo(0); + } + } + + @Test public void testResetLocal() throws Exception { Cursor localCursor = getLocalMediaCursor(LOCAL_ID, DATE_TAKEN_MS); // Add two cloud_ids mapping to the same local_id to verify that @@ -1216,7 +1298,7 @@ public class PickerDbFacadeTest { assertThat(cr.getCount()).isEqualTo(4); } - try (Cursor cr = mFacade.getMergedAlbums(qfb.build())) { + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), CLOUD_PROVIDER)) { assertThat(cr.getCount()).isEqualTo(2); cr.moveToFirst(); assertCloudAlbumCursor(cr, @@ -1269,7 +1351,7 @@ public class PickerDbFacadeTest { assertThat(cr.getCount()).isEqualTo(4); } - try (Cursor cr = mFacade.getMergedAlbums(qfb.build())) { + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), CLOUD_PROVIDER)) { assertThat(cr.getCount()).isEqualTo(2); cr.moveToFirst(); assertCloudAlbumCursor(cr, @@ -1288,7 +1370,7 @@ public class PickerDbFacadeTest { } qfb.setMimeTypes(IMAGE_MIME_TYPES_QUERY); - try (Cursor cr = mFacade.getMergedAlbums(qfb.build())) { + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), /* cloudProvider*/ null)) { assertThat(cr.getCount()).isEqualTo(1); cr.moveToFirst(); assertCloudAlbumCursor(cr, @@ -1299,8 +1381,19 @@ public class PickerDbFacadeTest { /* count */ 1); } + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), CLOUD_PROVIDER)) { + assertThat(cr.getCount()).isEqualTo(2); + cr.moveToFirst(); + assertCloudAlbumCursor(cr, + ALBUM_ID_FAVORITES, + ALBUM_ID_FAVORITES, + CLOUD_ID + "1", + DATE_TAKEN_MS, + /* count */ 1); + } + qfb.setMimeTypes(VIDEO_MIME_TYPES_QUERY); - try (Cursor cr = mFacade.getMergedAlbums(qfb.build())) { + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), CLOUD_PROVIDER)) { assertThat(cr.getCount()).isEqualTo(2); cr.moveToFirst(); assertCloudAlbumCursor(cr, @@ -1319,8 +1412,8 @@ public class PickerDbFacadeTest { } qfb.setMimeTypes(new String[]{"foo"}); - try (Cursor cr = mFacade.getMergedAlbums(qfb.build())) { - assertThat(cr.getCount()).isEqualTo(0); + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), CLOUD_PROVIDER)) { + assertThat(cr.getCount()).isEqualTo(2); } } @@ -1378,7 +1471,7 @@ public class PickerDbFacadeTest { // Verify that we see all available merged albums and their respective media count qfb.setIsLocalOnly(false); - try (Cursor cr = mFacade.getMergedAlbums(qfb.build())) { + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), CLOUD_PROVIDER)) { assertThat(cr.getCount()).isEqualTo(2); cr.moveToFirst(); assertCloudAlbumCursor(cr, @@ -1398,7 +1491,7 @@ public class PickerDbFacadeTest { qfb.setIsLocalOnly(true); // Verify that with isLocalOnly=true, we only see one album with only one local item. - try (Cursor cr = mFacade.getMergedAlbums(qfb.build())) { + try (Cursor cr = mFacade.getMergedAlbums(qfb.build(), /* cloudProvider */ null)) { assertThat(cr.getCount()).isEqualTo(1); cr.moveToFirst(); assertCloudAlbumCursor(cr, @@ -1789,4 +1882,4 @@ public class PickerDbFacadeTest { assertThat(cursor.getInt(cursor.getColumnIndex(PickerMediaColumns.ORIENTATION))) .isEqualTo(ORIENTATION); } -}
\ No newline at end of file +} diff --git a/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerActivityTest.java b/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerActivityTest.java index 92043fb90..a7a54126f 100644 --- a/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerActivityTest.java +++ b/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerActivityTest.java @@ -319,7 +319,11 @@ public class PhotoPickerActivityTest extends PhotoPickerBaseTest { @Test public void testResetOnCloudProviderChange() throws InterruptedException { // Enable cloud media feature for the activity through the test config store - mScenario.onActivity(activity -> activity.getConfigStore().enableCloudMediaFeature()); + mScenario.onActivity( + activity -> + activity.getConfigStore() + .enableCloudMediaFeatureAndSetAllowedCloudProviderPackages( + "com.hooli.super.awesome.cloud.provider")); // Switch to the albums tab onView(allOf(withText(PICKER_ALBUMS_STRING_ID), isDescendantOfA(withId(TAB_LAYOUT_ID)))) diff --git a/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerBaseTest.java b/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerBaseTest.java index 30b6efdda..965f3f33f 100644 --- a/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerBaseTest.java +++ b/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerBaseTest.java @@ -54,10 +54,10 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class PhotoPickerBaseTest { - protected static final int PICKER_TAB_RECYCLERVIEW_ID = R.id.picker_tab_recyclerview; - protected static final int TAB_LAYOUT_ID = R.id.tab_layout; + public static final int PICKER_TAB_RECYCLERVIEW_ID = R.id.picker_tab_recyclerview; + public static final int TAB_LAYOUT_ID = R.id.tab_layout; protected static final int PICKER_PHOTOS_STRING_ID = R.string.picker_photos; - protected static final int PICKER_ALBUMS_STRING_ID = R.string.picker_albums; + public static final int PICKER_ALBUMS_STRING_ID = R.string.picker_albums; protected static final int PREVIEW_VIEW_PAGER_ID = R.id.preview_viewPager; protected static final int ICON_CHECK_ID = R.id.icon_check; protected static final int ICON_THUMBNAIL_ID = R.id.icon_thumbnail; @@ -133,7 +133,7 @@ public class PhotoPickerBaseTest { private static final long POLLING_SLEEP_MILLIS = 200; private static IsolatedContext sIsolatedContext; - private static UserIdManager sUserIdManager; + static UserIdManager sUserIdManager; public static Intent getSingleSelectMimeTypeFilterIntent(String mimeTypeFilter) { final Intent intent = new Intent(sSingleSelectIntent); diff --git a/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerTestActivity.java b/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerTestActivity.java index c279abb77..242ad58b2 100644 --- a/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerTestActivity.java +++ b/tests/src/com/android/providers/media/photopicker/espresso/PhotoPickerTestActivity.java @@ -32,16 +32,18 @@ public class PhotoPickerTestActivity extends PhotoPickerActivity { private final UiEventLogger mLogger = mock(UiEventLogger.class, RETURNS_SMART_NULLS); private InstanceId mInstanceId; + private PickerViewModel mPickerViewModel; + @Override protected PickerViewModel getOrCreateViewModel() { - PickerViewModel pickerViewModel = super.getOrCreateViewModel(); - pickerViewModel.setConfigStore(mConfigStore); - pickerViewModel.setItemsProvider(new ItemsProvider( + mPickerViewModel = super.getOrCreateViewModel(); + mPickerViewModel.setConfigStore(mConfigStore); + mPickerViewModel.setItemsProvider(new ItemsProvider( PhotoPickerBaseTest.getIsolatedContext())); - pickerViewModel.setUserIdManager(PhotoPickerBaseTest.getMockUserIdManager()); - pickerViewModel.setLogger(new PhotoPickerUiEventLogger(mLogger)); - mInstanceId = pickerViewModel.getInstanceId(); - return pickerViewModel; + mPickerViewModel.setUserIdManager(PhotoPickerBaseTest.getMockUserIdManager()); + mPickerViewModel.setLogger(new PhotoPickerUiEventLogger(mLogger)); + mInstanceId = mPickerViewModel.getInstanceId(); + return mPickerViewModel; } TestConfigStore getConfigStore() { @@ -55,4 +57,12 @@ public class PhotoPickerTestActivity extends PhotoPickerActivity { InstanceId getInstanceId() { return mInstanceId; } + + void setItemsProvider(ItemsProvider itemsProvider) { + mPickerViewModel.setItemsProvider(itemsProvider); + } + + void initSyncForPhotosGrid() { + mPickerViewModel.initPhotoPickerData(); + } } diff --git a/tests/src/com/android/providers/media/photopicker/espresso/ProgressBarTest.java b/tests/src/com/android/providers/media/photopicker/espresso/ProgressBarTest.java new file mode 100644 index 000000000..a59ac46f5 --- /dev/null +++ b/tests/src/com/android/providers/media/photopicker/espresso/ProgressBarTest.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.media.photopicker.espresso; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static com.google.common.truth.Truth.assertWithMessage; + +import static org.hamcrest.Matchers.allOf; + +import android.content.Context; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject; +import android.support.test.uiautomator.UiSelector; +import android.text.format.DateUtils; + +import androidx.annotation.Nullable; +import androidx.test.core.app.ActivityScenario; +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; + +import com.android.providers.media.R; +import com.android.providers.media.library.RunOnlyOnPostsubmit; +import com.android.providers.media.photopicker.DataLoaderThread; +import com.android.providers.media.photopicker.data.ItemsProvider; +import com.android.providers.media.photopicker.data.model.UserId; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunOnlyOnPostsubmit +@RunWith(AndroidJUnit4ClassRunner.class) +public class ProgressBarTest extends PhotoPickerBaseTest { + public ActivityScenario<PhotoPickerTestActivity> mScenario; + protected static final UiDevice sDevice = UiDevice.getInstance(getInstrumentation()); + + @Before + public void setup() { + startPhotoPickerActivityAndEnableCloudFlag(); + } + + @Ignore("Enable progress bar and pagination tests after fixing the flaky behaviour b/296520260") + @Test + public void test_progressBarPhotosItems_isVisible() { + // To recreate the fragments with the new config. + mScenario.onActivity((PhotoPickerTestActivity::resetInCurrentProfile)); + DataLoaderThread.waitForIdle(); + + setItemsProviderWithDelayInActivity(); + + // Re-initiate sync to ensure that the progress bar comes into view. + mScenario.onActivity((PhotoPickerTestActivity::initSyncForPhotosGrid)); + + // Verify that the progress bar and loading text is visible. + assertProgressBarAndLoadingTextAppears(); + } + + + @Ignore("Enable progress bar and pagination tests after fixing the flaky behaviour b/296520260") + @Test + public void test_progressBarAlbumItems_isVisible() { + // Navigate to Albums tab + onView(allOf(withText(PICKER_ALBUMS_STRING_ID), isDescendantOfA(withId(TAB_LAYOUT_ID)))) + .perform(click()); + + setItemsProviderWithDelayInActivity(); + // Navigate to photos in Camera album + final int cameraStringId = R.string.picker_category_camera; + onView(allOf(withText(cameraStringId), + isDescendantOfA(withId(PICKER_TAB_RECYCLERVIEW_ID)))).perform(click()); + + // Verify that the progress bar and loading text is visible. + assertProgressBarAndLoadingTextAppears(); + } + + @Test + public void test_progressBarAlbumsTab_isNotVisible() { + + // Navigate to albums tab. + onView(allOf(withText(PICKER_ALBUMS_STRING_ID), isDescendantOfA(withId(TAB_LAYOUT_ID)))) + .perform(click()); + + // Verify that the progress bar and loading text is not visible. + assertProgressBarAndLoadingTextDoesNotAppears(); + } + + private void startPhotoPickerActivityAndEnableCloudFlag() { + sDevice.waitForIdle(); + launchPhotosActivity(); + mScenario.onActivity( + (activity -> { + activity.getConfigStore() + .enableCloudMediaFeatureAndSetAllowedCloudProviderPackages( + getInstrumentation().getTargetContext().getPackageName()); + })); + } + + private void launchPhotosActivity() { + mScenario = ActivityScenario.launchActivityForResult( + PhotoPickerBaseTest.getSingleSelectionIntent()); + } + + private void setItemsProviderWithDelayInActivity() { + FakeItemsProvider itemsProvider = new FakeItemsProvider(getIsolatedContext()); + itemsProvider.delaySync(); + mScenario.onActivity( + (activity -> { + activity.setItemsProvider(itemsProvider); + })); + } + + private void assertProgressBarAndLoadingTextAppears() { + final UiSelector progressBar = new UiSelector().resourceId( + getIsolatedContext().getPackageName() + + ":id/progress_bar"); + assertWithMessage("Waiting for progressBar to appear on photos grid").that( + new UiObject(progressBar).waitForExists(DateUtils.SECOND_IN_MILLIS)).isTrue(); + + final UiSelector loadingText = new UiSelector().resourceId( + getIsolatedContext().getPackageName() + + ":id/loading_text_view"); + assertWithMessage("Waiting for progressBar to appear on photos grid").that( + new UiObject(loadingText).waitForExists(DateUtils.SECOND_IN_MILLIS)).isTrue(); + } + + private void assertProgressBarAndLoadingTextDoesNotAppears() { + final UiSelector progressBar = new UiSelector().resourceId( + getIsolatedContext().getPackageName() + + ":id/progress_bar"); + assertWithMessage("Waiting for progressBar to appear on photos grid").that( + new UiObject(progressBar).waitForExists(DateUtils.SECOND_IN_MILLIS / 2)).isFalse(); + + final UiSelector loadingText = new UiSelector().resourceId( + getIsolatedContext().getPackageName() + + ":id/loading_text_view"); + assertWithMessage("Waiting for progressBar to appear on photos grid").that( + new UiObject(loadingText).waitForExists(DateUtils.SECOND_IN_MILLIS / 2)).isFalse(); + } + + @After + public void tearDown() { + if (mScenario != null) { + mScenario.close(); + } + } + + public static class FakeItemsProvider extends ItemsProvider { + + private boolean mShouldDelaySync = false; + + public FakeItemsProvider(Context context) { + super(context); + } + + public void delaySync() { + mShouldDelaySync = true; + } + + @Override + public void initPhotoPickerData(@Nullable String albumId, + @Nullable String albumAuthority, + boolean initLocalOnlyData, + @Nullable UserId userId) { + if (mShouldDelaySync) { + try { + Thread.sleep(DateUtils.SECOND_IN_MILLIS); + } catch (Exception e) { + // no-op + } + } else { + super.initPhotoPickerData(albumId, albumAuthority, initLocalOnlyData, userId); + } + } + } +} diff --git a/tests/src/com/android/providers/media/photopicker/sync/MediaResetWorkerTest.java b/tests/src/com/android/providers/media/photopicker/sync/MediaResetWorkerTest.java new file mode 100644 index 000000000..62ee3377c --- /dev/null +++ b/tests/src/com/android/providers/media/photopicker/sync/MediaResetWorkerTest.java @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.media.photopicker.sync; + +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_LOCAL_AND_CLOUD; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_RESET_ALBUM; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_AUTHORITY; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_RESET_TYPE; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_SYNC_SOURCE; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_TAG_IS_PERIODIC; +import static com.android.providers.media.photopicker.sync.SyncWorkerTestUtils.getAlbumResetInputData; +import static com.android.providers.media.photopicker.sync.SyncWorkerTestUtils.initializeTestWorkManager; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import android.content.Context; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.os.Build; +import android.provider.CloudMediaProviderContract.MediaColumns; + +import androidx.test.filters.SdkSuppress; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.work.Data; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkInfo; +import androidx.work.WorkManager; + +import com.android.providers.media.photopicker.PickerSyncController; +import com.android.providers.media.photopicker.data.PickerDatabaseHelper; +import com.android.providers.media.photopicker.data.PickerDbFacade; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; + +import java.io.File; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +// TODO enable tests in Android R after fixing b/293390235 +@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) +public class MediaResetWorkerTest { + + private PickerSyncController mExistingPickerSyncController; + + @Mock private PickerSyncController mMockPickerSyncController; + @Mock private SyncTracker mMockLocalAlbumSyncTracker; + @Mock private SyncTracker mMockCloudAlbumSyncTracker; + + private PickerDbFacade mDbFacade; + private Context mContext; + + private static final String TEST_ALBUM_ID_1 = "test-album-id-1"; + private static final String TEST_ALBUM_ID_2 = "test-album-id-2"; + private static final String TEST_ALBUM_ID_3 = "test-album-id-3"; + private static final String TEST_ALBUM_ID_4 = "test-album-id-4"; + private static final String TEST_LOCAL_AUTHORITY = "com.android.media.photopicker"; + private static final String TEST_CLOUD_AUTHORITY = "com.hooli.super.awesome.cloud.provider"; + + @Before + public void setup() { + initMocks(this); + + try { + mExistingPickerSyncController = PickerSyncController.getInstanceOrThrow(); + } catch (IllegalStateException ignored) { + } + + // Inject mock trackers + SyncTrackerRegistry.setLocalAlbumSyncTracker(mMockLocalAlbumSyncTracker); + SyncTrackerRegistry.setCloudAlbumSyncTracker(mMockCloudAlbumSyncTracker); + + doReturn(new Object()).when(mMockPickerSyncController).getCloudAlbumSyncLock(); + doReturn(TEST_CLOUD_AUTHORITY).when(mMockPickerSyncController).getCloudProvider(); + doReturn(TEST_LOCAL_AUTHORITY).when(mMockPickerSyncController).getLocalProvider(); + + mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + // Cleanup previous test run databases. + File dbPath = mContext.getDatabasePath(PickerDatabaseHelper.PICKER_DATABASE_NAME); + dbPath.delete(); + + mDbFacade = new PickerDbFacade(mContext, TEST_LOCAL_AUTHORITY); + mDbFacade.setCloudProvider(TEST_CLOUD_AUTHORITY); + + initializeTestWorkManager(mContext); + PickerSyncController.setInstance(mMockPickerSyncController); + } + + @After + public void teardown() { + if (mExistingPickerSyncController != null) { + PickerSyncController.setInstance(mExistingPickerSyncController); + } + + // Reset mock trackers + SyncTrackerRegistry.setLocalAlbumSyncTracker(new SyncTracker()); + SyncTrackerRegistry.setCloudAlbumSyncTracker(new SyncTracker()); + } + + @Test + public void testResetCloudAlbumMediaForAlbumId() + throws ExecutionException, InterruptedException { + + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_1, TEST_CLOUD_AUTHORITY); + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_2, TEST_CLOUD_AUTHORITY); + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_3, TEST_LOCAL_AUTHORITY); + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_4, TEST_LOCAL_AUTHORITY); + + final OneTimeWorkRequest request = + new OneTimeWorkRequest.Builder(MediaResetWorker.class) + .setInputData( + getAlbumResetInputData( + TEST_ALBUM_ID_1, TEST_CLOUD_AUTHORITY, false)) + .build(); + + final WorkManager workManager = WorkManager.getInstance(mContext); + workManager.enqueue(request).getResult().get(); + + // Verify + final WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get(); + assertThat(workInfo.getState()).isEqualTo(WorkInfo.State.SUCCEEDED); + + // We should have deleted just the rows related to the TEST_ALBUM_ID_1 album. + Cursor cursor = queryAlbumMediaAll(TEST_CLOUD_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(60); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_ALBUM_ID_1, TEST_CLOUD_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(0); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_ALBUM_ID_2, TEST_CLOUD_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(20); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_ALBUM_ID_3, TEST_LOCAL_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(20); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_ALBUM_ID_4, TEST_LOCAL_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(20); + cursor.close(); + + // The sync future is created by the PickerSyncManager before the request is + // enqueued. + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 0)) + .createSyncFuture(any()); + + // The worker should resolve its own sync future. + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + } + + @Test + public void testResetLocalAlbumMediaForAlbumId() + throws ExecutionException, InterruptedException { + + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_1, TEST_LOCAL_AUTHORITY); + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_2, TEST_CLOUD_AUTHORITY); + + final OneTimeWorkRequest request = + new OneTimeWorkRequest.Builder(MediaResetWorker.class) + .setInputData( + getAlbumResetInputData(TEST_ALBUM_ID_1, TEST_CLOUD_AUTHORITY, true)) + .build(); + + final WorkManager workManager = WorkManager.getInstance(mContext); + workManager.enqueue(request).getResult().get(); + + // Verify + final WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get(); + assertThat(workInfo.getState()).isEqualTo(WorkInfo.State.SUCCEEDED); + + + // We should have deleted just the rows related to the TEST_ALBUM_ID_1 album. + Cursor cursor = queryAlbumMediaAll(TEST_CLOUD_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(20); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_ALBUM_ID_1, TEST_LOCAL_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(0); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_ALBUM_ID_2, TEST_CLOUD_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(20); + cursor.close(); + + // The sync future is created by the PickerSyncManager before the request is + // enqueued. + verify(mMockLocalAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 0)) + .createSyncFuture(any()); + + // The worker should resolve its own sync future. + verify(mMockLocalAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + } + + @Test + public void testResetAllAlbumMedia() throws ExecutionException, InterruptedException { + + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_1, TEST_CLOUD_AUTHORITY); + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_2, TEST_CLOUD_AUTHORITY); + + final Data requestData = + new Data( + Map.of( + SYNC_WORKER_INPUT_AUTHORITY, + TEST_CLOUD_AUTHORITY, + SYNC_WORKER_INPUT_RESET_TYPE, + SYNC_RESET_ALBUM, + SYNC_WORKER_INPUT_SYNC_SOURCE, + SYNC_LOCAL_AND_CLOUD)); + + final OneTimeWorkRequest request = + new OneTimeWorkRequest.Builder(MediaResetWorker.class) + .setInputData(requestData) + .build(); + + final WorkManager workManager = WorkManager.getInstance(mContext); + workManager.enqueue(request).getResult().get(); + + // Verify + final WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get(); + assertThat(workInfo.getState()).isEqualTo(WorkInfo.State.SUCCEEDED); + + Cursor cursor = queryAlbumMediaAll(TEST_CLOUD_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(0); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_LOCAL_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(0); + cursor.close(); + + // The sync future is created by the PickerSyncManager before the request is + // enqueued. + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 0)) + .createSyncFuture(any()); + + // The worker should resolve its own sync future. + verify(mMockLocalAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + } + + @Test + public void testPeriodicWorkerAlbumReset_WithCloudProvider() + throws ExecutionException, InterruptedException { + + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_1, TEST_LOCAL_AUTHORITY); + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_2, TEST_CLOUD_AUTHORITY); + + final Data requestData = + new Data( + Map.of( + SYNC_WORKER_INPUT_RESET_TYPE, + SYNC_RESET_ALBUM, + SYNC_WORKER_INPUT_SYNC_SOURCE, + SYNC_LOCAL_AND_CLOUD)); + + final OneTimeWorkRequest request = + new OneTimeWorkRequest.Builder(MediaResetWorker.class) + .setInputData(requestData) + .addTag(SYNC_WORKER_TAG_IS_PERIODIC) + .build(); + + final WorkManager workManager = WorkManager.getInstance(mContext); + workManager.enqueue(request).getResult().get(); + + // Verify + final WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get(); + assertThat(workInfo.getState()).isEqualTo(WorkInfo.State.SUCCEEDED); + + // The sync future is created by the PickerSyncManager before the request is + // enqueued. + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .createSyncFuture(any()); + verify(mMockLocalAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .createSyncFuture(any()); + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + verify(mMockLocalAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + + Cursor cursor = queryAlbumMediaAll(TEST_CLOUD_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(0); + cursor.close(); + + cursor = queryAlbumMediaAll(TEST_LOCAL_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(0); + cursor.close(); + } + + @Test + public void testPeriodicWorkerAlbumReset_WithLocalProvider() + throws ExecutionException, InterruptedException { + + doReturn(null).when(mMockPickerSyncController).getCloudProvider(); + + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_1, TEST_LOCAL_AUTHORITY); + assertAddAlbumMediaWithAlbumId(TEST_ALBUM_ID_2, TEST_LOCAL_AUTHORITY); + + final Data requestData = + new Data( + Map.of( + SYNC_WORKER_INPUT_RESET_TYPE, + SYNC_RESET_ALBUM, + SYNC_WORKER_INPUT_SYNC_SOURCE, + SYNC_LOCAL_AND_CLOUD)); + + final OneTimeWorkRequest request = + new OneTimeWorkRequest.Builder(MediaResetWorker.class) + .setInputData(requestData) + .addTag(SYNC_WORKER_TAG_IS_PERIODIC) + .build(); + + final WorkManager workManager = WorkManager.getInstance(mContext); + workManager.enqueue(request).getResult().get(); + + // Verify + final WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get(); + assertThat(workInfo.getState()).isEqualTo(WorkInfo.State.SUCCEEDED); + + // The sync future is created by the PickerSyncManager before the request is + // enqueued. + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .createSyncFuture(any()); + verify(mMockLocalAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .createSyncFuture(any()); + verify(mMockCloudAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + verify(mMockLocalAlbumSyncTracker, times(/* wantedNumberOfInvocations */ 1)) + .markSyncCompleted(any()); + + Cursor cursor = queryAlbumMediaAll(TEST_LOCAL_AUTHORITY); + assertThat(cursor.getCount()).isEqualTo(0); + cursor.close(); + } + + /** + * Builds a suitible mock Album media cursor that could be returned from a provider. + * + * @param id a base id for each file. will be appended with the current loop count. + */ + private static Cursor getAlbumMediaCursor(String id) { + String[] projectionKey = + new String[] { + MediaColumns.ID, + MediaColumns.MEDIA_STORE_URI, + MediaColumns.DATE_TAKEN_MILLIS, + MediaColumns.SYNC_GENERATION, + MediaColumns.SIZE_BYTES, + MediaColumns.MIME_TYPE, + MediaColumns.STANDARD_MIME_TYPE_EXTENSION, + MediaColumns.DURATION_MILLIS, + }; + + MatrixCursor c = new MatrixCursor(projectionKey); + int counter = 0; + + while (++counter <= 20) { + + String[] projectionValue = + new String[] { + id + counter, + "content://media/external/file/1234" + counter, + String.valueOf(System.nanoTime()), + String.valueOf(1), + String.valueOf(1234), + "image/png", + String.valueOf(MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE), + String.valueOf(1234), + }; + + c.addRow(projectionValue); + } + return c; + } + + /** + * Query all records in the Album media table. + * + * @param authority provider's authority + */ + private Cursor queryAlbumMediaAll(String authority) { + return mDbFacade.queryAlbumMediaForUi( + new PickerDbFacade.QueryFilterBuilder(1000).build(), authority); + } + + /** + * @param albumId limit the results to just files present in this album + * @param authority provider's authority + */ + private Cursor queryAlbumMediaAll(String albumId, String authority) { + return mDbFacade.queryAlbumMediaForUi( + new PickerDbFacade.QueryFilterBuilder(1000).setAlbumId(albumId).build(), authority); + } + + /** + * Creates a fake Album with the given Album ID and adds 20 fake files to it. + * + * @param albumId the id to use in creating the fake album + * @param authority the provider that owns the fake album. + */ + private void assertAddAlbumMediaWithAlbumId(String albumId, String authority) { + + try (PickerDbFacade.DbWriteOperation operation = + mDbFacade.beginAddAlbumMediaOperation(authority, albumId)) { + operation.execute(getAlbumMediaCursor("1234-" + albumId)); + operation.setSuccess(); + } + + Cursor cr = queryAlbumMediaAll(albumId, authority); + assertThat(cr.getCount()).isEqualTo(20); + } +} diff --git a/tests/src/com/android/providers/media/photopicker/sync/PickerSyncManagerTest.java b/tests/src/com/android/providers/media/photopicker/sync/PickerSyncManagerTest.java index d066d7788..3cd2858c6 100644 --- a/tests/src/com/android/providers/media/photopicker/sync/PickerSyncManagerTest.java +++ b/tests/src/com/android/providers/media/photopicker/sync/PickerSyncManagerTest.java @@ -25,22 +25,31 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.initMocks; +import android.content.Context; +import android.content.res.Resources; + import androidx.work.ExistingPeriodicWorkPolicy; import androidx.work.ExistingWorkPolicy; import androidx.work.OneTimeWorkRequest; import androidx.work.Operation; import androidx.work.PeriodicWorkRequest; +import androidx.work.WorkContinuation; +import androidx.work.WorkInfo; import androidx.work.WorkManager; import androidx.work.WorkRequest; +import com.android.modules.utils.BackgroundThread; import com.android.providers.media.TestConfigStore; +import com.android.providers.media.photopicker.PickerSyncController; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; import org.junit.Before; import org.junit.Test; @@ -48,7 +57,12 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class PickerSyncManagerTest { private PickerSyncManager mPickerSyncManager; @@ -58,32 +72,40 @@ public class PickerSyncManagerTest { @Mock private Operation mMockOperation; @Mock + private WorkContinuation mMockWorkContinuation; + @Mock private ListenableFuture<Operation.State.SUCCESS> mMockFuture; + @Mock + private Context mMockContext; + @Mock + private Resources mResources; @Captor ArgumentCaptor<PeriodicWorkRequest> mPeriodicWorkRequestArgumentCaptor; @Captor ArgumentCaptor<OneTimeWorkRequest> mOneTimeWorkRequestArgumentCaptor; @Captor - ArgumentCaptor<List<WorkRequest>> mWorkRequestListArgumentCaptor; + ArgumentCaptor<List<OneTimeWorkRequest>> mOneTimeWorkRequestListArgumentCaptor; @Before public void setUp() { initMocks(this); + doReturn(mResources).when(mMockContext).getResources(); mConfigStore = new TestConfigStore(); - mConfigStore.enableCloudMediaFeature(); + mConfigStore.enableCloudMediaFeatureAndSetAllowedCloudProviderPackages( + "com.hooli.super.awesome.cloudpicker"); } @Test public void testSchedulePeriodicSyncs() { setupPickerSyncManager(/* schedulePeriodicSyncs */ true); - verify(mMockWorkManager, times(1)) + verify(mMockWorkManager, times(2)) .enqueueUniquePeriodicWork(anyString(), any(), mPeriodicWorkRequestArgumentCaptor.capture()); final PeriodicWorkRequest periodicWorkRequest = - mPeriodicWorkRequestArgumentCaptor.getValue(); + mPeriodicWorkRequestArgumentCaptor.getAllValues().get(0); assertThat(periodicWorkRequest.getWorkSpec().workerClassName) .isEqualTo(ProactiveSyncWorker.class.getName()); assertThat(periodicWorkRequest.getWorkSpec().expedited).isFalse(); @@ -93,6 +115,77 @@ public class PickerSyncManagerTest { assertThat(periodicWorkRequest.getWorkSpec().input .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) .isEqualTo(SYNC_LOCAL_AND_CLOUD); + + final PeriodicWorkRequest periodicResetRequest = + mPeriodicWorkRequestArgumentCaptor.getAllValues().get(1); + assertThat(periodicResetRequest.getWorkSpec().workerClassName) + .isEqualTo(MediaResetWorker.class.getName()); + assertThat(periodicResetRequest.getWorkSpec().expedited).isFalse(); + assertThat(periodicResetRequest.getWorkSpec().isPeriodic()).isTrue(); + assertThat(periodicResetRequest.getWorkSpec().id).isNotNull(); + assertThat(periodicResetRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isTrue(); + assertThat(periodicResetRequest.getWorkSpec().constraints.requiresDeviceIdle()).isTrue(); + assertThat(periodicResetRequest.getWorkSpec().input + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + .isEqualTo(SYNC_LOCAL_AND_CLOUD); + } + + @Test + public void testPeriodicWorkIsScheduledOnDeviceConfigChanges() { + + mConfigStore.disableCloudMediaFeature(); + + + setupPickerSyncManager(true); + + // Ensure no syncs have been scheduled yet. + verify(mMockWorkManager, times(0)) + .enqueueUniquePeriodicWork(anyString(), + any(), + mPeriodicWorkRequestArgumentCaptor.capture()); + + mConfigStore.enableCloudMediaFeatureAndSetAllowedCloudProviderPackages( + "com.hooli.some.cloud.provider"); + + waitForIdle(); + + // Ensure the syncs are now scheduled. + verify(mMockWorkManager, times(2)) + .enqueueUniquePeriodicWork(anyString(), + any(), + mPeriodicWorkRequestArgumentCaptor.capture()); + + final PeriodicWorkRequest periodicWorkRequest = + mPeriodicWorkRequestArgumentCaptor.getAllValues().get(0); + assertThat(periodicWorkRequest.getWorkSpec().workerClassName) + .isEqualTo(ProactiveSyncWorker.class.getName()); + assertThat(periodicWorkRequest.getWorkSpec().expedited).isFalse(); + assertThat(periodicWorkRequest.getWorkSpec().isPeriodic()).isTrue(); + assertThat(periodicWorkRequest.getWorkSpec().id).isNotNull(); + assertThat(periodicWorkRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isTrue(); + assertThat(periodicWorkRequest.getWorkSpec().input + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + .isEqualTo(SYNC_LOCAL_AND_CLOUD); + + final PeriodicWorkRequest periodicResetRequest = + mPeriodicWorkRequestArgumentCaptor.getAllValues().get(1); + assertThat(periodicResetRequest.getWorkSpec().workerClassName) + .isEqualTo(MediaResetWorker.class.getName()); + assertThat(periodicResetRequest.getWorkSpec().expedited).isFalse(); + assertThat(periodicResetRequest.getWorkSpec().isPeriodic()).isTrue(); + assertThat(periodicResetRequest.getWorkSpec().id).isNotNull(); + assertThat(periodicResetRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isTrue(); + assertThat(periodicResetRequest.getWorkSpec().constraints.requiresDeviceIdle()).isTrue(); + assertThat(periodicResetRequest.getWorkSpec().input + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + .isEqualTo(SYNC_LOCAL_AND_CLOUD); + + clearInvocations(mMockWorkManager); + + mConfigStore.disableCloudMediaFeature(); + waitForIdle(); + + verify(mMockWorkManager, times(2)).cancelUniqueWork(anyString()); } @Test @@ -123,11 +216,9 @@ public class PickerSyncManagerTest { mPickerSyncManager.syncMediaImmediately(true); verify(mMockWorkManager, times(1)) - .enqueue(mWorkRequestListArgumentCaptor.capture()); + .enqueueUniqueWork(anyString(), any(), mOneTimeWorkRequestArgumentCaptor.capture()); - final List<WorkRequest> workRequestList = mWorkRequestListArgumentCaptor.getValue(); - assertThat(workRequestList.size()).isEqualTo(1); - WorkRequest workRequest = workRequestList.get(0); + final OneTimeWorkRequest workRequest = mOneTimeWorkRequestArgumentCaptor.getValue(); assertThat(workRequest.getWorkSpec().workerClassName) .isEqualTo(ImmediateSyncWorker.class.getName()); assertThat(workRequest.getWorkSpec().expedited).isTrue(); @@ -144,42 +235,71 @@ public class PickerSyncManagerTest { setupPickerSyncManager(/* schedulePeriodicSyncs */ false); mPickerSyncManager.syncMediaImmediately(false); - verify(mMockWorkManager, times(1)) - .enqueue(mWorkRequestListArgumentCaptor.capture()); + verify(mMockWorkManager, times(2)) + .enqueueUniqueWork(anyString(), any(), mOneTimeWorkRequestArgumentCaptor.capture()); - final List<WorkRequest> workRequestList = mWorkRequestListArgumentCaptor.getValue(); - assertThat(workRequestList.size()).isEqualTo(1); - WorkRequest workRequest = workRequestList.get(0); - assertThat(workRequest.getWorkSpec().workerClassName) + final List<OneTimeWorkRequest> workRequestList = + mOneTimeWorkRequestArgumentCaptor.getAllValues(); + assertThat(workRequestList.size()).isEqualTo(2); + + WorkRequest localWorkRequest = workRequestList.get(0); + assertThat(localWorkRequest.getWorkSpec().workerClassName) .isEqualTo(ImmediateSyncWorker.class.getName()); - assertThat(workRequest.getWorkSpec().expedited).isTrue(); - assertThat(workRequest.getWorkSpec().isPeriodic()).isFalse(); - assertThat(workRequest.getWorkSpec().id).isNotNull(); - assertThat(workRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isFalse(); - assertThat(workRequest.getWorkSpec().input + assertThat(localWorkRequest.getWorkSpec().expedited).isTrue(); + assertThat(localWorkRequest.getWorkSpec().isPeriodic()).isFalse(); + assertThat(localWorkRequest.getWorkSpec().id).isNotNull(); + assertThat(localWorkRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isFalse(); + assertThat(localWorkRequest.getWorkSpec().input .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) - .isEqualTo(SYNC_LOCAL_AND_CLOUD); + .isEqualTo(SYNC_LOCAL_ONLY); + + WorkRequest cloudWorkRequest = workRequestList.get(1); + assertThat(cloudWorkRequest.getWorkSpec().workerClassName) + .isEqualTo(ImmediateSyncWorker.class.getName()); + assertThat(cloudWorkRequest.getWorkSpec().expedited).isTrue(); + assertThat(cloudWorkRequest.getWorkSpec().isPeriodic()).isFalse(); + assertThat(cloudWorkRequest.getWorkSpec().id).isNotNull(); + assertThat(cloudWorkRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isFalse(); + assertThat(cloudWorkRequest.getWorkSpec().input + .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + .isEqualTo(SYNC_CLOUD_ONLY); } @Test public void testImmediateLocalAlbumSync() { setupPickerSyncManager(/* schedulePeriodicSyncs */ false); - mPickerSyncManager.syncAlbumMediaForProviderImmediately("Not_null", true); + mPickerSyncManager.syncAlbumMediaForProviderImmediately( + "Not_null", PickerSyncController.LOCAL_PICKER_PROVIDER_AUTHORITY); verify(mMockWorkManager, times(1)) - .enqueue(mWorkRequestListArgumentCaptor.capture()); + .beginUniqueWork( + anyString(), + any(ExistingWorkPolicy.class), + mOneTimeWorkRequestListArgumentCaptor.capture()); + verify(mMockWorkContinuation, times(1)) + .then(mOneTimeWorkRequestListArgumentCaptor.capture()); + verify(mMockWorkContinuation).enqueue(); - final List<WorkRequest> workRequestList = mWorkRequestListArgumentCaptor.getValue(); - assertThat(workRequestList.size()).isEqualTo(1); - WorkRequest workRequest = workRequestList.get(0); + final OneTimeWorkRequest resetRequest = + mOneTimeWorkRequestListArgumentCaptor.getAllValues().get(0).get(0); + assertThat(resetRequest.getWorkSpec().workerClassName) + .isEqualTo(MediaResetWorker.class.getName()); + assertThat(resetRequest.getWorkSpec().expedited).isTrue(); + assertThat(resetRequest.getWorkSpec().isPeriodic()).isFalse(); + assertThat(resetRequest.getWorkSpec().id).isNotNull(); + assertThat(resetRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isFalse(); + assertThat(resetRequest.getWorkSpec().input.getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + .isEqualTo(SYNC_LOCAL_ONLY); + + final OneTimeWorkRequest workRequest = + mOneTimeWorkRequestListArgumentCaptor.getAllValues().get(1).get(0); assertThat(workRequest.getWorkSpec().workerClassName) .isEqualTo(ImmediateAlbumSyncWorker.class.getName()); assertThat(workRequest.getWorkSpec().expedited).isTrue(); assertThat(workRequest.getWorkSpec().isPeriodic()).isFalse(); assertThat(workRequest.getWorkSpec().id).isNotNull(); assertThat(workRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isFalse(); - assertThat(workRequest.getWorkSpec().input - .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + assertThat(workRequest.getWorkSpec().input.getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) .isEqualTo(SYNC_LOCAL_ONLY); } @@ -187,24 +307,75 @@ public class PickerSyncManagerTest { public void testImmediateCloudAlbumSync() { setupPickerSyncManager(/* schedulePeriodicSyncs */ false); - mPickerSyncManager.syncAlbumMediaForProviderImmediately("Not_null", false); + mPickerSyncManager.syncAlbumMediaForProviderImmediately( + "Not_null", "com.hooli.cloudpicker"); verify(mMockWorkManager, times(1)) - .enqueue(mWorkRequestListArgumentCaptor.capture()); + .beginUniqueWork( + anyString(), + any(ExistingWorkPolicy.class), + mOneTimeWorkRequestListArgumentCaptor.capture()); + verify(mMockWorkContinuation, times(1)) + .then(mOneTimeWorkRequestListArgumentCaptor.capture()); + verify(mMockWorkContinuation).enqueue(); - final List<WorkRequest> workRequestList = mWorkRequestListArgumentCaptor.getValue(); - assertThat(workRequestList.size()).isEqualTo(1); - WorkRequest workRequest = workRequestList.get(0); + final OneTimeWorkRequest resetRequest = + mOneTimeWorkRequestListArgumentCaptor.getAllValues().get(0).get(0); + assertThat(resetRequest.getWorkSpec().workerClassName) + .isEqualTo(MediaResetWorker.class.getName()); + assertThat(resetRequest.getWorkSpec().expedited).isTrue(); + assertThat(resetRequest.getWorkSpec().isPeriodic()).isFalse(); + assertThat(resetRequest.getWorkSpec().id).isNotNull(); + assertThat(resetRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isFalse(); + assertThat(resetRequest.getWorkSpec().input.getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + .isEqualTo(SYNC_CLOUD_ONLY); + + final OneTimeWorkRequest workRequest = + mOneTimeWorkRequestListArgumentCaptor.getAllValues().get(1).get(0); assertThat(workRequest.getWorkSpec().workerClassName) .isEqualTo(ImmediateAlbumSyncWorker.class.getName()); assertThat(workRequest.getWorkSpec().expedited).isTrue(); assertThat(workRequest.getWorkSpec().isPeriodic()).isFalse(); assertThat(workRequest.getWorkSpec().id).isNotNull(); assertThat(workRequest.getWorkSpec().constraints.requiresBatteryNotLow()).isFalse(); - assertThat(workRequest.getWorkSpec().input - .getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) + assertThat(workRequest.getWorkSpec().input.getInt(SYNC_WORKER_INPUT_SYNC_SOURCE, -1)) .isEqualTo(SYNC_CLOUD_ONLY); } + @Test + public void testUniqueWorkStatusForPendingWork() { + setupPickerSyncManager(/* schedulePeriodicSyncs */ false); + final String workName = "testWorkName"; + final SettableFuture<List<WorkInfo>> future = SettableFuture.create(); + final List<WorkInfo> futureResult = new ArrayList<>(); + futureResult.add(getWorkInfo(WorkInfo.State.SUCCEEDED)); + futureResult.add(getWorkInfo(WorkInfo.State.ENQUEUED)); + future.set(futureResult); + doReturn(future).when(mMockWorkManager) + .getWorkInfosForUniqueWork(workName); + + assertThat(mPickerSyncManager.isUniqueWorkPending(workName)).isTrue(); + } + + @Test + public void testUniqueWorkStatusForCompletedWork() { + setupPickerSyncManager(/* schedulePeriodicSyncs */ false); + final String workName = "testWorkName"; + final SettableFuture<List<WorkInfo>> future = SettableFuture.create(); + final List<WorkInfo> futureResult = new ArrayList<>(); + futureResult.add(getWorkInfo(WorkInfo.State.SUCCEEDED)); + futureResult.add(getWorkInfo(WorkInfo.State.FAILED)); + futureResult.add(getWorkInfo(WorkInfo.State.CANCELLED)); + future.set(futureResult); + doReturn(future).when(mMockWorkManager) + .getWorkInfosForUniqueWork(workName); + + assertThat(mPickerSyncManager.isUniqueWorkPending(workName)).isFalse(); + } + + private WorkInfo getWorkInfo(WorkInfo.State state) { + return new WorkInfo(UUID.randomUUID(), state, new HashSet<>()); + } + private void setupPickerSyncManager(boolean schedulePeriodicSyncs) { doReturn(mMockOperation).when(mMockWorkManager) .enqueueUniquePeriodicWork(anyString(), @@ -214,9 +385,31 @@ public class PickerSyncManagerTest { .enqueueUniqueWork(anyString(), any(ExistingWorkPolicy.class), any(OneTimeWorkRequest.class)); + doReturn(mMockWorkContinuation) + .when(mMockWorkManager) + .beginUniqueWork( + anyString(), any(ExistingWorkPolicy.class), any(List.class)); + // Handle .then chaining + doReturn(mMockWorkContinuation) + .when(mMockWorkContinuation) + .then(any(List.class)); + doReturn(mMockOperation).when(mMockWorkContinuation).enqueue(); doReturn(mMockFuture).when(mMockOperation).getResult(); mPickerSyncManager = - new PickerSyncManager(mMockWorkManager, mConfigStore, schedulePeriodicSyncs); + new PickerSyncManager(mMockWorkManager, mMockContext, + mConfigStore, schedulePeriodicSyncs); } + + private static void waitForIdle() { + final CountDownLatch latch = new CountDownLatch(1); + BackgroundThread.getExecutor().execute(latch::countDown); + try { + latch.await(30, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + + } + } diff --git a/tests/src/com/android/providers/media/photopicker/sync/SyncWorkerTestUtils.java b/tests/src/com/android/providers/media/photopicker/sync/SyncWorkerTestUtils.java index 24408e104..de621d9f3 100644 --- a/tests/src/com/android/providers/media/photopicker/sync/SyncWorkerTestUtils.java +++ b/tests/src/com/android/providers/media/photopicker/sync/SyncWorkerTestUtils.java @@ -19,7 +19,10 @@ package com.android.providers.media.photopicker.sync; import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_CLOUD_ONLY; import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_LOCAL_AND_CLOUD; import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_LOCAL_ONLY; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_RESET_ALBUM; import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_ALBUM_ID; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_AUTHORITY; +import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_RESET_TYPE; import static com.android.providers.media.photopicker.sync.PickerSyncManager.SYNC_WORKER_INPUT_SYNC_SOURCE; import android.content.Context; @@ -63,6 +66,19 @@ public class SyncWorkerTestUtils { } @NonNull + public static Data getAlbumResetInputData( + @NonNull String albumId, String authority, boolean isLocal) { + Objects.requireNonNull(albumId); + Objects.requireNonNull(authority); + return new Data( + Map.of( + SYNC_WORKER_INPUT_AUTHORITY, authority, + SYNC_WORKER_INPUT_SYNC_SOURCE, isLocal ? SYNC_LOCAL_ONLY : SYNC_CLOUD_ONLY, + SYNC_WORKER_INPUT_RESET_TYPE, SYNC_RESET_ALBUM, + SYNC_WORKER_INPUT_ALBUM_ID, albumId)); + } + + @NonNull public static Data getCloudAlbumSyncInputData(@NonNull String albumId) { Objects.requireNonNull(albumId); return new Data(Map.of(SYNC_WORKER_INPUT_SYNC_SOURCE, SYNC_CLOUD_ONLY, diff --git a/tests/src/com/android/providers/media/photopicker/util/CloudProviderUtilsTest.java b/tests/src/com/android/providers/media/photopicker/util/CloudProviderUtilsTest.java new file mode 100644 index 000000000..8649d4d56 --- /dev/null +++ b/tests/src/com/android/providers/media/photopicker/util/CloudProviderUtilsTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.media.photopicker.util; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.InstrumentationRegistry; + +import com.android.providers.media.IsolatedContext; +import com.android.providers.media.TestConfigStore; +import com.android.providers.media.cloudproviders.CloudProviderPrimary; +import com.android.providers.media.cloudproviders.CloudProviderSecondary; +import com.android.providers.media.cloudproviders.FlakyCloudProvider; +import com.android.providers.media.photopicker.data.CloudProviderInfo; + +import org.junit.Test; + +import java.util.List; +import java.util.Set; + + +public class CloudProviderUtilsTest { + + @Test + public void getAllAvailableCloudProvidersTest() { + final Context context = InstrumentationRegistry.getTargetContext(); + final Context isolatedContext = + new IsolatedContext(context, "CloudProviderUtilsTest", /*asFuseThread*/ false); + final Set<String> testCloudProviders = Set.of( + FlakyCloudProvider.AUTHORITY, + CloudProviderPrimary.AUTHORITY, + CloudProviderSecondary.AUTHORITY); + final TestConfigStore configStore = new TestConfigStore(); + configStore.enableCloudMediaFeatureAndSetAllowedCloudProviderPackages( + testCloudProviders.toArray(new String[0])); + + List<CloudProviderInfo> availableProviders = + CloudProviderUtils.getAllAvailableCloudProviders(isolatedContext, configStore); + + assertThat(availableProviders.size()).isEqualTo(testCloudProviders.size()); + for (CloudProviderInfo info : availableProviders) { + assertThat(testCloudProviders.contains(info.authority)).isTrue(); + } + } +} diff --git a/tests/src/com/android/providers/media/photopicker/viewmodel/BannerControllerTest.java b/tests/src/com/android/providers/media/photopicker/viewmodel/BannerControllerTest.java index d1f8a5899..05ccbbe4f 100644 --- a/tests/src/com/android/providers/media/photopicker/viewmodel/BannerControllerTest.java +++ b/tests/src/com/android/providers/media/photopicker/viewmodel/BannerControllerTest.java @@ -16,19 +16,30 @@ package com.android.providers.media.photopicker.viewmodel; +import static android.provider.MediaStore.AUTHORITY; +import static android.provider.MediaStore.getCurrentCloudProvider; + import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.android.providers.media.photopicker.util.CloudProviderUtils.persistSelectedProvider; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import android.content.ContentProviderClient; +import android.content.ContentResolver; import android.content.Context; +import android.os.RemoteException; +import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.providers.media.IsolatedContext; import com.android.providers.media.TestConfigStore; +import com.android.providers.media.cloudproviders.FlakyCloudProvider; import org.junit.Before; import org.junit.Test; @@ -36,37 +47,37 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class BannerControllerTest { - private BannerController mBannerController; + private static final Context sTargetContext = getInstrumentation().getTargetContext(); + private static final String TEST_PACKAGE_NAME = "com.android.providers.media.tests"; private static final String CMP_AUTHORITY = "authority"; private static final String CMP_ACCOUNT_NAME = "account_name"; - private static final String TAG = "BannerControllerTest"; + + private IsolatedContext mIsolatedContext; + private ContentResolver mContentResolver; + private BannerController mBannerController; @Before - public void setUp() { - final Context context = new IsolatedContext( - getInstrumentation().getTargetContext(), TAG, /* asFuseThread= */ false); + public void setUp() throws RemoteException { final TestConfigStore configStore = new TestConfigStore(); + configStore.enableCloudMediaFeatureAndSetAllowedCloudProviderPackages(TEST_PACKAGE_NAME); - mBannerController = new BannerController(context, context.getUser(), configStore) { - @Override - void updateCloudProviderDataFile() { - // No-op - } + mIsolatedContext = new IsolatedContext(sTargetContext, /* tag= */ "databases", + /* asFuseThread= */ false, sTargetContext.getUser(), configStore); + mContentResolver = mIsolatedContext.getContentResolver(); - @Override - boolean areCloudProviderOptionsAvailable() { - return true; - } - }; + setCloudProvider(/* authority= */ null); + + mBannerController = + new BannerController(mIsolatedContext, mIsolatedContext.getUser(), configStore) { + @Override + void updateCloudProviderDataFile() { + // No-op + } + }; assertNull(mBannerController.getCloudMediaProviderAuthority()); assertNull(mBannerController.getCloudMediaProviderLabel()); assertNull(mBannerController.getCloudMediaProviderAccountName()); - - assertFalse(mBannerController.shouldShowCloudMediaAvailableBanner()); - assertFalse(mBannerController.shouldShowAccountUpdatedBanner()); - assertFalse(mBannerController.shouldShowChooseAccountBanner()); - assertFalse(mBannerController.shouldShowChooseAppBanner()); } @Test @@ -150,4 +161,51 @@ public class BannerControllerTest { assertFalse(mBannerController.shouldShowChooseAccountBanner()); assertFalse(mBannerController.shouldShowChooseAppBanner()); } + + @Test + public void testCloudProviderSlowQueryFallback() throws RemoteException { + setCloudProvider(FlakyCloudProvider.AUTHORITY); + + // Test for fast query + mIsolatedContext.resetFlakyCloudProviderToNotFlakeInTheNextRequest(); + mBannerController.onChangeCloudMediaInfo( + /* cmpAuthority */ null, /* cmpAccountName */ null); + mBannerController.reset(); + + assertEquals(FlakyCloudProvider.AUTHORITY, + mBannerController.getCloudMediaProviderAuthority()); + assertEquals(FlakyCloudProvider.ACCOUNT_NAME, + mBannerController.getCloudMediaProviderAccountName()); + + assertTrue(mBannerController.shouldShowCloudMediaAvailableBanner()); + assertFalse(mBannerController.shouldShowAccountUpdatedBanner()); + assertFalse(mBannerController.shouldShowChooseAccountBanner()); + assertFalse(mBannerController.shouldShowChooseAppBanner()); + + // Test for slow query + mIsolatedContext.setFlakyCloudProviderToFlakeInTheNextRequest(); + mBannerController.onChangeCloudMediaInfo( + /* cmpAuthority */ null, /* cmpAccountName */ null); + mBannerController.reset(); + + assertEquals(FlakyCloudProvider.AUTHORITY, + mBannerController.getCloudMediaProviderAuthority()); + assertNull(mBannerController.getCloudMediaProviderAccountName()); + + assertFalse(mBannerController.shouldShowCloudMediaAvailableBanner()); + assertFalse(mBannerController.shouldShowAccountUpdatedBanner()); + assertFalse(mBannerController.shouldShowChooseAccountBanner()); + assertFalse(mBannerController.shouldShowChooseAppBanner()); + } + + private void setCloudProvider(@Nullable String authority) throws RemoteException { + final ContentProviderClient client = + mContentResolver.acquireContentProviderClient(AUTHORITY); + assertNotNull(client); + + persistSelectedProvider(client, authority); + + final String actualAuthority = getCurrentCloudProvider(mContentResolver); + assertEquals(authority, actualAuthority); + } } diff --git a/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelPaginationTest.java b/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelPaginationTest.java index d9385b455..44b0cb83e 100644 --- a/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelPaginationTest.java +++ b/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelPaginationTest.java @@ -58,6 +58,7 @@ import com.android.providers.media.photopicker.data.model.Item; import com.android.providers.media.photopicker.data.model.UserId; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -134,8 +135,8 @@ public class PickerViewModelPaginationTest { // Get live data for items, this also loads the first page. LiveData<PickerViewModel.PaginatedItemsResult> testItems = mPickerViewModel.getPaginatedItemsForAction( - ACTION_VIEW_CREATED, new - PaginationParameters(pageSize, -1, -1)); + ACTION_VIEW_CREATED, new PaginationParameters( + pageSize, /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); // Empty list should be returned. @@ -169,7 +170,8 @@ public class PickerViewModelPaginationTest { LiveData<PickerViewModel.PaginatedItemsResult> testItems = mPickerViewModel.getPaginatedCategoryItemsForAction( downloadsAlbum, ACTION_VIEW_CREATED, - new PaginationParameters(pageSize, -1, -1)); + new PaginationParameters( + pageSize, /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); // Empty list should be returned. @@ -201,8 +203,8 @@ public class PickerViewModelPaginationTest { // Get live data for items, this also loads the first page. LiveData<PickerViewModel.PaginatedItemsResult> testItems = mPickerViewModel.getPaginatedItemsForAction( - ACTION_VIEW_CREATED, new - PaginationParameters(pageSize, -1, -1)); + ACTION_VIEW_CREATED, new PaginationParameters( + pageSize, /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); // Page 1: Since the page size is set to 4, only 4 images should be returned. @@ -237,6 +239,7 @@ public class PickerViewModelPaginationTest { } } + @Ignore("Enable progress bar and pagination tests after fixing the flaky behaviour b/296520260") @Test public void test_differentCategories_getCategoryItems() throws Exception { int pageSize = 4; @@ -260,7 +263,8 @@ public class PickerViewModelPaginationTest { LiveData<PickerViewModel.PaginatedItemsResult> testItems = mPickerViewModel.getPaginatedCategoryItemsForAction( cameraAlbum, ACTION_VIEW_CREATED, - new PaginationParameters(pageSize, -1, -1)); + new PaginationParameters( + pageSize, /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); // Page 1: Since the page size is set to 4, only 4 images should be returned. @@ -296,7 +300,8 @@ public class PickerViewModelPaginationTest { LiveData<PickerViewModel.PaginatedItemsResult> testItemsDownloads = mPickerViewModel.getPaginatedCategoryItemsForAction( downloadsAlbum, ACTION_VIEW_CREATED, - new PaginationParameters(pageSize, -1, -1)); + new PaginationParameters( + pageSize, /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); // Page 1: Since the page size is set to 4, only 4 images should be returned. @@ -349,7 +354,8 @@ public class PickerViewModelPaginationTest { // Get live data for items, this also loads the first page. LiveData<PickerViewModel.PaginatedItemsResult> testItems = mPickerViewModel.getPaginatedItemsForAction( - ACTION_VIEW_CREATED, new PaginationParameters(pageSize, -1, -1)); + ACTION_VIEW_CREATED, new PaginationParameters(pageSize, + /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); // Page 1: Since the page size is set to 4, only 4 images should be returned. @@ -392,7 +398,8 @@ public class PickerViewModelPaginationTest { // loaded. LiveData<PickerViewModel.PaginatedItemsResult> testItems = mPickerViewModel.getPaginatedItemsForAction( - ACTION_VIEW_CREATED, new PaginationParameters(pageSize, -1, -1)); + ACTION_VIEW_CREATED, new PaginationParameters(pageSize, + /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); assertThat(testItems.getValue().getItems().size()).isEqualTo(pageSize); @@ -409,7 +416,8 @@ public class PickerViewModelPaginationTest { // Call updateItems which is usually called on profile switch or reset. // This should clear out the list and load the first page. mPickerViewModel.getPaginatedItemsForAction(ACTION_REFRESH_ITEMS, - new PaginationParameters(pageSize, -1, -1)); + new PaginationParameters( + pageSize, /*dateBeforeMs*/ Long.MIN_VALUE, /* rowId*/ -1)); DataLoaderThread.waitForIdle(); // Assert that only one page of items are present now. diff --git a/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelTest.java b/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelTest.java index 817e5af19..947154c55 100644 --- a/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelTest.java +++ b/tests/src/com/android/providers/media/photopicker/viewmodel/PickerViewModelTest.java @@ -89,6 +89,8 @@ import java.util.concurrent.TimeUnit; public class PickerViewModelTest { private static final String FAKE_CATEGORY_NAME = "testCategoryName"; private static final String FAKE_ID = "5"; + private static final String FAKE_CLOUD_MEDIA_PROVIDER_PACKAGE_NAME = + "com.hooli.super.awesome.cloud.provider"; private static final Context sTargetContext = getInstrumentation().getTargetContext(); @Rule @@ -111,6 +113,8 @@ public class PickerViewModelTest { when(mApplication.getApplicationContext()).thenReturn(sTargetContext); mConfigStore = new TestConfigStore(); mConfigStore.enableCloudMediaFeature(); + mConfigStore.setAllowedCloudProviderPackages( + new String[]{FAKE_CLOUD_MEDIA_PROVIDER_PACKAGE_NAME}); getInstrumentation().runOnMainSync(() -> { mPickerViewModel = new PickerViewModel(mApplication) { @Override diff --git a/tests/src/com/android/providers/media/stableuris/dao/BackupIdRowTest.java b/tests/src/com/android/providers/media/stableuris/dao/BackupIdRowTest.java index bfadf87af..f0087355b 100644 --- a/tests/src/com/android/providers/media/stableuris/dao/BackupIdRowTest.java +++ b/tests/src/com/android/providers/media/stableuris/dao/BackupIdRowTest.java @@ -44,8 +44,9 @@ public class BackupIdRowTest { .setIsTrashed(0) .setOwnerPackagedId(1) .setUserId(1) - .setDateExpires("10") + .setDateExpires(null) .setIsDirty(true) + .setMediaType(1) .build(); String s = BackupIdRow.serialize(row); @@ -59,6 +60,7 @@ public class BackupIdRowTest { .setUserId(1) .setDateExpires("10") .setIsDirty(false) + .setMediaType(0) .build(); assertThat(BackupIdRow.deserialize(s)).isNotEqualTo(row2); |