From 8e50c5d198f65beb6679a9a1e0102e5fc52d7707 Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka" <takaoka@google.com>
Date: Mon, 7 May 2012 01:47:14 +0900
Subject: [PATCH] Fix subtype name for a custom input style with en_US and
 en_GB

This change utilizes "UntranslatableReplacementStringInSubtypeName"
subtype extra value to display keyboard layout name dynamically.

Bug: 6449315
Change-Id: I9ef4c3d66ff9a223aa8c89c346d04cb72e4f6263
---
 java/res/values/donottranslate.xml            |  4 +-
 java/res/values/strings.xml                   |  6 +++
 .../inputmethod/latin/AdditionalSubtype.java  | 18 +++++++--
 .../android/inputmethod/latin/Constants.java  | 19 +++++++---
 .../inputmethod/latin/SubtypeLocale.java      | 38 ++++++++++++++++---
 5 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 4fe447e20..73aa54f7e 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -134,7 +134,9 @@
         <item>5</item>
     </string-array>
 
-    <!-- Subtype locale display name exceptions -->
+    <!-- Subtype locale display name exceptions.
+         For each exception, there should be related string resource for display name that has
+         explicit keyboard layout. The string resource name must be "subtype_with_layout_<locale>. -->
     <string-array name="subtype_locale_exception_keys">
         <item>en_US</item>
         <item>en_GB</item>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 69fdea79f..cb458a4ed 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -252,6 +252,12 @@
     <string name="subtype_en_GB">English (UK)</string>
     <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=25] -->
     <string name="subtype_en_US">English (US)</string>
+    <!-- Description for English (United Kingdom) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
+         This should be identical to subtype_en_GB aside from the trailing (%s). -->
+    <string name="subtype_with_layout_en_GB">English (UK) (<xliff:g id="layout">%s</xliff:g>)</string>
+    <!-- Description for English (United States) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
+         This should be identical to subtype_en_US aside from the trailing (%s). -->
+    <string name="subtype_with_layout_en_US">English (US) (<xliff:g id="layout">%s</xliff:g>)</string>
     <!-- Description for language agnostic keyboard subtype [CHAR LIMIT=25] -->
     <string name="subtype_no_language">No language</string>
     <!-- Description for language agnostic QWERTY keyboard subtype [CHAR LIMIT=25] -->
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
index 06d33154f..a6e7a82f1 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
@@ -19,7 +19,9 @@ package com.android.inputmethod.latin;
 import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
 
+import android.os.Build;
 import android.view.inputmethod.InputMethodSubtype;
 
 import java.util.ArrayList;
@@ -40,12 +42,22 @@ public class AdditionalSubtype {
     public static InputMethodSubtype createAdditionalSubtype(
             String localeString, String keyboardLayoutSetName, String extraValue) {
         final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
-        final String filteredExtraValue = StringUtils.appendToCsvIfNotExists(
-                IS_ADDITIONAL_SUBTYPE, extraValue);
+        final String layoutDisplayNameExtraValue;
+        if (SubtypeLocale.isExceptionalLocale(localeString)
+                && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName(
+                    keyboardLayoutSetName);
+            layoutDisplayNameExtraValue = StringUtils.appendToCsvIfNotExists(
+                    UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME + "=" + layoutDisplayName, extraValue);
+        } else {
+            layoutDisplayNameExtraValue = extraValue;
+        }
+        final String additionalSubtypeExtraValue = StringUtils.appendToCsvIfNotExists(
+                IS_ADDITIONAL_SUBTYPE, layoutDisplayNameExtraValue);
         final int nameId = SubtypeLocale.getSubtypeNameId(localeString, keyboardLayoutSetName);
         return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
                 localeString, KEYBOARD_MODE,
-                layoutExtraValue + "," + filteredExtraValue, false, false);
+                layoutExtraValue + "," + additionalSubtypeExtraValue, false, false);
     }
 
     public static String getPrefSubtype(InputMethodSubtype subtype) {
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index b205cc004..7c2284569 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -64,11 +64,6 @@ public final class Constants {
         public static final String KEYBOARD_MODE = "keyboard";
 
         public static final class ExtraValue {
-            /**
-             * The subtype extra value used to indicate that the subtype keyboard layout set name.
-             */
-            public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
-
             /**
              * The subtype extra value used to indicate that the subtype keyboard layout is capable
              * for typing ASCII characters.
@@ -81,6 +76,20 @@ public final class Constants {
              */
             public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity";
 
+            /**
+             * The subtype extra value used to indicate that the subtype display name contains "%s"
+             * for replacement mark and it should be replaced by this extra value.
+             * This extra value is supported on JellyBean and later.
+             */
+            public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
+                    "UntranslatableReplacementStringInSubtypeName";
+
+            /**
+             * The subtype extra value used to indicate that the subtype keyboard layout set name.
+             * This extra value is private to LatinIME.
+             */
+            public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
+
             /**
              * The subtype extra value used to indicate that the subtype is additional subtype
              * that the user defined. This extra value is private to LatinIME.
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index b7e488410..354a0c8df 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -17,9 +17,11 @@
 package com.android.inputmethod.latin;
 
 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.os.Build;
 import android.util.Log;
 import android.view.inputmethod.InputMethodSubtype;
 
@@ -41,13 +43,18 @@ public class SubtypeLocale {
 
     private static String[] sPredefinedKeyboardLayoutSet;
     // Keyboard layout to its display name map.
-    private static final HashMap<String, String> sKeyboardKayoutToDisplayNameMap =
+    private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap =
             new HashMap<String, String>();
     // Keyboard layout to subtype name resource id map.
     private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap =
             new HashMap<String, Integer>();
+    // Exceptional locale to subtype name resource id map.
+    private static final HashMap<String, Integer> sExceptionalLocaleToWithLayoutNameIdsMap =
+            new HashMap<String, Integer>();
     private static final String SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX =
             "string/subtype_generic_";
+    private static final String SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX =
+            "string/subtype_with_layout_";
     private static final String SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX =
             "string/subtype_no_language_";
     // Exceptional locales to display name map.
@@ -67,7 +74,7 @@ public class SubtypeLocale {
                 R.array.predefined_layout_display_names);
         for (int i = 0; i < predefinedLayoutSet.length; i++) {
             final String layoutName = predefinedLayoutSet[i];
-            sKeyboardKayoutToDisplayNameMap.put(layoutName, layoutDisplayNames[i]);
+            sKeyboardLayoutToDisplayNameMap.put(layoutName, layoutDisplayNames[i]);
             final String resourceName = SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX + layoutName;
             final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
             sKeyboardLayoutToNameIdsMap.put(layoutName, resId);
@@ -84,7 +91,11 @@ public class SubtypeLocale {
         final String[] exceptionalDisplayNames = res.getStringArray(
                 R.array.subtype_locale_exception_values);
         for (int i = 0; i < exceptionalLocales.length; i++) {
-            sExceptionalDisplayNamesMap.put(exceptionalLocales[i], exceptionalDisplayNames[i]);
+            final String localeString = exceptionalLocales[i];
+            sExceptionalDisplayNamesMap.put(localeString, exceptionalDisplayNames[i]);
+            final String resourceName = SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX + localeString;
+            final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
+            sExceptionalLocaleToWithLayoutNameIdsMap.put(localeString, resId);
         }
     }
 
@@ -92,11 +103,19 @@ public class SubtypeLocale {
         return sPredefinedKeyboardLayoutSet;
     }
 
+    public static boolean isExceptionalLocale(String localeString) {
+        return sExceptionalLocaleToWithLayoutNameIdsMap.containsKey(localeString);
+    }
+
     private static final String getNoLanguageLayoutKey(String keyboardLayoutName) {
         return NO_LANGUAGE + "_" + keyboardLayoutName;
     }
 
     public static int getSubtypeNameId(String localeString, String keyboardLayoutName) {
+        if (isExceptionalLocale(localeString)
+                && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            return sExceptionalLocaleToWithLayoutNameIdsMap.get(localeString);
+        }
         final String key = localeString.equals(NO_LANGUAGE)
                 ? getNoLanguageLayoutKey(keyboardLayoutName)
                 : keyboardLayoutName;
@@ -129,13 +148,16 @@ public class SubtypeLocale {
     //  zz    azerty T  No language (AZERTY)    in system locale
 
     public static String getSubtypeDisplayName(final InputMethodSubtype subtype, Resources res) {
-        final String language = getSubtypeLocaleDisplayName(subtype.getLocale());
+        final String replacementString =
+                subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
+                ? subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
+                : getSubtypeLocaleDisplayName(subtype.getLocale());
         final int nameResId = subtype.getNameResId();
         final RunInLocale<String> getSubtypeName = new RunInLocale<String>() {
             @Override
             protected String job(Resources res) {
                 try {
-                    return res.getString(nameResId, language);
+                    return res.getString(nameResId, replacementString);
                 } catch (Resources.NotFoundException e) {
                     // TODO: Remove this catch when InputMethodManager.getCurrentInputMethodSubtype
                     // is fixed.
@@ -164,7 +186,11 @@ public class SubtypeLocale {
 
     public static String getKeyboardLayoutSetDisplayName(InputMethodSubtype subtype) {
         final String layoutName = getKeyboardLayoutSetName(subtype);
-        return sKeyboardKayoutToDisplayNameMap.get(layoutName);
+        return getKeyboardLayoutSetDisplayName(layoutName);
+    }
+
+    public static String getKeyboardLayoutSetDisplayName(String layoutName) {
+        return sKeyboardLayoutToDisplayNameMap.get(layoutName);
     }
 
     public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) {