Merge "Import translations. DO NOT MERGE" into arc-apps
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ef7f14b..d3819d8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -218,17 +218,35 @@
     <!-- Label of the close dialog button.[CHAR LIMIT=24] -->
     <string name="close">Close</string>
     <!-- Contents of the copying failure alert dialog. [CHAR LIMIT=48] -->
-    <string name="copy_failure_alert_content">These files weren\u2019t copied: <xliff:g id="list">%1$s</xliff:g></string>
+    <plurals name="copy_failure_alert_content">
+        <item quantity="one">This file wasn\u2019t copied: <xliff:g id="list" example="Document.pdf">%1$s</xliff:g></item>
+        <item quantity="other">These files weren\u2019t copied: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></item>
+    </plurals>
     <!-- Contents of the compressing failure alert dialog. [CHAR LIMIT=48] -->
-    <string name="compress_failure_alert_content">These files weren\u2019t compressed: <xliff:g id="list">%1$s</xliff:g></string>
+    <plurals name="compress_failure_alert_content">
+        <item quantity="one">This file wasn\u2019t compressed: <xliff:g id="list" example="Document.pdf">%1$s</xliff:g></item>
+        <item quantity="other">These files weren\u2019t compressed: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></item>
+    </plurals>
     <!-- Contents of the extracting failure alert dialog. [CHAR LIMIT=48] -->
-    <string name="extract_failure_alert_content">These files weren\u2019t extracted: <xliff:g id="list">%1$s</xliff:g></string>
+    <plurals name="extract_failure_alert_content">
+        <item quantity="one">This file wasn\u2019t extracted: <xliff:g id="list" example="Document.pdf">%1$s</xliff:g></item>
+        <item quantity="other">These files weren\u2019t extracted: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></item>
+    </plurals>
     <!-- Contents of the moving failure alert dialog. [CHAR LIMIT=48] -->
-    <string name="move_failure_alert_content">These files weren\u2019t moved: <xliff:g id="list">%1$s</xliff:g></string>
-    <!-- Message shown to users when an operation to delete one or more files has failed. Presented in a dialog. [CHAR LIMIT=48] -->
-    <string name="delete_failure_alert_content">These files weren\u2019t deleted: <xliff:g id="list">%1$s</xliff:g></string>
+    <plurals name="move_failure_alert_content">
+        <item quantity="one">This file wasn\u2019t moved: <xliff:g id="list" example="Document.pdf">%1$s</xliff:g></item>
+        <item quantity="other">These files weren\u2019t moved: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></item>
+    </plurals>
+    <!-- Contents of the deleting failure alert dialog. [CHAR LIMIT=48] -->
+    <plurals name="delete_failure_alert_content">
+        <item quantity="one">This file wasn\u2019t deleted: <xliff:g id="list" example="Document.pdf">%1$s</xliff:g></item>
+        <item quantity="other">These files weren\u2019t deleted: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></item>
+    </plurals>
     <!-- Contents of the copying warning dialog due to converted files. [CHAR LIMIT=64] -->
-    <string name="copy_converted_warning_content">These files were converted to another format: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></string>
+    <plurals name="copy_converted_warning_content">
+        <item quantity="one">This file was converted to another format: <xliff:g id="list" example="Document.pdf">%1$s</xliff:g></item>
+        <item quantity="other">These files were converted to another format: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></item>
+    </plurals>
     <!-- Toast shown when a user copies files to clipboard. -->
     <plurals name="clipboard_files_clipped">
         <item quantity="one">Copied <xliff:g id="count" example="1">%1$d</xliff:g> file to clipboard.</item>
diff --git a/src/com/android/documentsui/OperationDialogFragment.java b/src/com/android/documentsui/OperationDialogFragment.java
index 8b0b70e..c13fea0 100644
--- a/src/com/android/documentsui/OperationDialogFragment.java
+++ b/src/com/android/documentsui/OperationDialogFragment.java
@@ -31,10 +31,12 @@
 import com.android.documentsui.base.DocumentStack;
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperationService.OpType;
+import com.android.documentsui.ui.MessageBuilder;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+
 /**
  * Alert dialog for operation dialogs.
  */
@@ -67,6 +69,7 @@
         args.putInt(FileOperationService.EXTRA_DIALOG_TYPE, dialogType);
         args.putInt(FileOperationService.EXTRA_OPERATION_TYPE, operationType);
         args.putParcelableArrayList(FileOperationService.EXTRA_FAILED_DOCS, failedSrcList);
+        args.putParcelableArrayList(FileOperationService.EXTRA_FAILED_URIS, uriList);
 
         final FragmentTransaction ft = fm.beginTransaction();
         final OperationDialogFragment fragment = new OperationDialogFragment();
@@ -90,51 +93,10 @@
                 FileOperationService.EXTRA_FAILED_DOCS);
 
         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-        String messageFormat;
+        final String message = new MessageBuilder(getContext()).generateListMessage(
+                dialogType, operationType, docList, uriList);
 
-        switch (dialogType) {
-            case DIALOG_TYPE_CONVERTED:
-                messageFormat = getString(R.string.copy_converted_warning_content);
-                break;
-
-            case DIALOG_TYPE_FAILURE:
-                switch (operationType) {
-                    case FileOperationService.OPERATION_COPY:
-                        messageFormat = getString(R.string.copy_failure_alert_content);
-                        break;
-                    case FileOperationService.OPERATION_COMPRESS:
-                        messageFormat = getString(R.string.compress_failure_alert_content);
-                        break;
-                    case FileOperationService.OPERATION_EXTRACT:
-                        messageFormat = getString(R.string.extract_failure_alert_content);
-                        break;
-                    case FileOperationService.OPERATION_DELETE:
-                        messageFormat = getString(R.string.delete_failure_alert_content);
-                        break;
-                    case FileOperationService.OPERATION_MOVE:
-                        messageFormat = getString(R.string.move_failure_alert_content);
-                        break;
-                    default:
-                        throw new UnsupportedOperationException();
-                }
-                break;
-
-            default:
-                throw new UnsupportedOperationException();
-        }
-
-        final StringBuilder list = new StringBuilder("<p>");
-        for (DocumentInfo documentInfo : docList) {
-            list.append("&#8226; " + Html.escapeHtml(documentInfo.displayName) + "<br>");
-        }
-        if (uriList != null) {
-            for (Uri uri : uriList) {
-                list.append("&#8226; " + uri.toSafeString() + "<br>");
-            }
-        }
-        list.append("</p>");
-
-        builder.setMessage(Html.fromHtml(String.format(messageFormat, list.toString())));
+        builder.setMessage(Html.fromHtml(message));
         builder.setPositiveButton(
                 R.string.close,
                 new DialogInterface.OnClickListener() {
diff --git a/src/com/android/documentsui/files/MenuManager.java b/src/com/android/documentsui/files/MenuManager.java
index f0acb3f..1089e6a 100644
--- a/src/com/android/documentsui/files/MenuManager.java
+++ b/src/com/android/documentsui/files/MenuManager.java
@@ -213,7 +213,8 @@
     @Override
     protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
         share.setVisible(!selectionDetails.containsDirectories()
-                && !selectionDetails.containsPartialFiles());
+                && !selectionDetails.containsPartialFiles()
+                && !selectionDetails.canExtract());
     }
 
     @Override
diff --git a/src/com/android/documentsui/ui/MessageBuilder.java b/src/com/android/documentsui/ui/MessageBuilder.java
index dc3a638..4a4af29 100644
--- a/src/com/android/documentsui/ui/MessageBuilder.java
+++ b/src/com/android/documentsui/ui/MessageBuilder.java
@@ -18,10 +18,19 @@
 import android.annotation.PluralsRes;
 import android.content.Context;
 import android.text.BidiFormatter;
+import android.net.Uri;
+import android.text.Html;
 
+import com.android.documentsui.OperationDialogFragment.DialogType;
 import com.android.documentsui.R;
 import com.android.documentsui.base.DocumentInfo;
 import com.android.documentsui.base.Shared;
+import com.android.documentsui.services.FileOperationService;
+import com.android.documentsui.services.FileOperationService.OpType;
+import com.android.documentsui.OperationDialogFragment.DialogType;
+
+import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_FAILURE;
+import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_CONVERTED;
 
 import java.util.List;
 
@@ -70,6 +79,59 @@
         return message;
     }
 
+    public String generateListMessage(
+            @DialogType int dialogType, @OpType int operationType, List<DocumentInfo> docs,
+            List<Uri> uris) {
+        int resourceId;
+
+        switch (dialogType) {
+            case DIALOG_TYPE_CONVERTED:
+                resourceId = R.plurals.copy_converted_warning_content;
+                break;
+
+            case DIALOG_TYPE_FAILURE:
+                switch (operationType) {
+                    case FileOperationService.OPERATION_COPY:
+                        resourceId = R.plurals.copy_failure_alert_content;
+                        break;
+                    case FileOperationService.OPERATION_COMPRESS:
+                        resourceId = R.plurals.compress_failure_alert_content;
+                        break;
+                    case FileOperationService.OPERATION_EXTRACT:
+                        resourceId = R.plurals.extract_failure_alert_content;
+                        break;
+                    case FileOperationService.OPERATION_DELETE:
+                        resourceId = R.plurals.delete_failure_alert_content;
+                        break;
+                    case FileOperationService.OPERATION_MOVE:
+                        resourceId = R.plurals.move_failure_alert_content;
+                        break;
+                    default:
+                        throw new UnsupportedOperationException();
+                }
+                break;
+
+            default:
+                throw new UnsupportedOperationException();
+        }
+
+        final StringBuilder list = new StringBuilder("<p>");
+        for (DocumentInfo documentInfo : docs) {
+            list.append("&#8226; " + Html.escapeHtml(BidiFormatter.getInstance().unicodeWrap(
+                    documentInfo.displayName)) + "<br>");
+        }
+        if (uris != null) {
+            for (Uri uri : uris) {
+                list.append("&#8226; " + BidiFormatter.getInstance().unicodeWrap(uri.toSafeString()) +
+                        "<br>");
+            }
+        }
+        list.append("</p>");
+
+        final int totalItems = docs.size() + (uris != null ? uris.size() : 0);
+        return mContext.getResources().getQuantityString(resourceId, totalItems, list.toString());
+    }
+
     /**
      * Generates a formatted quantity string.
      */
diff --git a/tests/unit/com/android/documentsui/files/MenuManagerTest.java b/tests/unit/com/android/documentsui/files/MenuManagerTest.java
index a15fe93..540d22b 100644
--- a/tests/unit/com/android/documentsui/files/MenuManagerTest.java
+++ b/tests/unit/com/android/documentsui/files/MenuManagerTest.java
@@ -177,13 +177,14 @@
     }
 
     @Test
-    public void testActionMenu_canExtract_hidesCopyToAndCompressTo() {
+    public void testActionMenu_canExtract_hidesCopyToAndCompressToAndShare() {
         selectionDetails.canExtract = true;
         mgr.updateActionMenu(testMenu, selectionDetails);
 
         extractTo.assertEnabled();
         copyTo.assertDisabled();
         compressTo.assertDisabled();
+        share.assertInvisible();
     }
 
     @Test