diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 247bdba412c61c57d908a53a22439c650ab22410..2a3d705b0758992eb55f4c5a3e7d5a817dd3b24b 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -332,11 +332,11 @@
     <!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]-->
     <string name="keyboard_layout">Keyboard theme</string>
 
-    <!-- Description for German QWERTY keyboard subtype [CHAR LIMIT=35] -->
+    <!-- Description for German QWERTY keyboard subtype [CHAR LIMIT=22] -->
     <string name="subtype_de_qwerty">German QWERTY</string>
-    <!-- Description for English (United Kingdom) keyboard subtype [CHAR LIMIT=35] -->
+    <!-- Description for English (United Kingdom) keyboard subtype [CHAR LIMIT=22] -->
     <string name="subtype_en_GB">English (UK)</string>
-    <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=35] -->
+    <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=22] -->
     <string name="subtype_en_US">English (US)</string>
 
     <!-- Title of an option for usability study mode -->
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 452294e04eb80829cdb3f4529378a9c1fdc36c2e..f2f3178de7bb6b63e37e6eb247b6871c15ed8fc1 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -20,7 +20,7 @@
 <!-- The attributes in this XML file provide configuration information -->
 <!-- for the Input Method Manager. -->
 
-<!-- Keyboard: en_US, en_GB, ar, cs, da, de, de_ZZ, es, es_US, fi, fr, fr_CA, fr_CH, hr, hu, it, iw, nb, nl, pl, pt, ru, sr, sv, tr -->
+<!-- Keyboard: en_US, en_GB, ar, cs, da, de, de(QWERTY), es, es_US, fi, fr, fr_CA, fr_CH, hr, hu, it, iw, nb, nl, pl, pt, ru, sr, sv, tr -->
 <!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. -->
 <!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default
      subtype.-->
@@ -64,9 +64,9 @@
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_de_qwerty"
-            android:imeSubtypeLocale="de_ZZ"
+            android:imeSubtypeLocale="de"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
index 7aab66d058129c6c0af8ae3fc450ad24e9caa7ef..8e2ee0f7a8c06a4c01d97532c31820a54d611d2b 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
@@ -73,16 +73,17 @@ public class InputMethodServiceCompatWrapper extends InputMethodService {
     // This call is required to let LatinIME itself know a subtype changed
     // event when the API level is 10 or previous.
     @SuppressWarnings("unused")
-    public void notifyOnCurrentInputMethodSubtypeChanged(InputMethodSubtypeCompatWrapper subtype) {
+    public void notifyOnCurrentInputMethodSubtypeChanged(
+            InputMethodSubtypeCompatWrapper newSubtype) {
         // Do nothing when the API level is 11 or later
         // and FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES is not true
         if (CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED && !InputMethodManagerCompatWrapper.
                 FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) {
             return;
         }
-        if (subtype == null) {
-            subtype = mImm.getCurrentInputMethodSubtype();
-        }
+        final InputMethodSubtypeCompatWrapper subtype = (newSubtype == null)
+                ? mImm.getCurrentInputMethodSubtype()
+                : newSubtype;
         if (subtype != null) {
             if (!InputMethodManagerCompatWrapper.FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES
                     && !subtype.isDummy()) return;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 7559108f3c7d81ad2550f8619cccd7de09357369..da6c22107d3db9692cb9f4c03145e44f1020ce63 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -118,6 +118,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
      */
     public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
 
+    /**
+     * The subtype extra value used to indicate that the subtype keyboard layout should be loaded
+     * from the specified locale.
+     */
+    public static final String SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE = "KeyboardLocale";
+
     private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
 
     // How many continuous deletes at which to start deleting at a higher speed.
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 87d8549407a3833acd069ca3a12a19df9b4091f3..a60f444fb9a4f7b693f917973573fc0d6a96b259 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -138,7 +138,7 @@ public class SubtypeSwitcher {
         mEnabledLanguagesOfCurrentInputMethod.clear();
         mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
         for (InputMethodSubtypeCompatWrapper ims : mAllEnabledSubtypesOfCurrentInputMethod) {
-            final String locale = ims.getLocale();
+            final String locale = getSubtypeLocale(ims);
             final String mode = ims.getMode();
             mLocaleSplitter.setString(locale);
             if (mLocaleSplitter.hasNext()) {
@@ -167,7 +167,7 @@ public class SubtypeSwitcher {
             Log.d(TAG, "Update shortcut IME from : "
                     + (mShortcutInputMethodInfo == null
                             ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
-                    + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale()
+                    + (mShortcutSubtype == null ? "<null>" : (getSubtypeLocale(mShortcutSubtype)
                             + ", " + mShortcutSubtype.getMode())));
         }
         // TODO: Update an icon for shortcut IME
@@ -189,11 +189,17 @@ public class SubtypeSwitcher {
             Log.d(TAG, "Update shortcut IME to : "
                     + (mShortcutInputMethodInfo == null
                             ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
-                    + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale()
+                    + (mShortcutSubtype == null ? "<null>" : (getSubtypeLocale(mShortcutSubtype)
                             + ", " + mShortcutSubtype.getMode())));
         }
     }
 
+    private static String getSubtypeLocale(InputMethodSubtypeCompatWrapper subtype) {
+        final String keyboardLocale = subtype.getExtraValueOf(
+                LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE);
+        return keyboardLocale != null ? keyboardLocale : subtype.getLocale();
+    }
+
     // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
     public void updateSubtype(InputMethodSubtypeCompatWrapper newSubtype) {
         final String newLocale;
@@ -206,7 +212,7 @@ public class SubtypeSwitcher {
             newLocale = "en_US";
             newMode = KEYBOARD_MODE;
         } else {
-            newLocale = newSubtype.getLocale();
+            newLocale = getSubtypeLocale(newSubtype);
             newMode = newSubtype.getMode();
         }
         if (DBG) {
@@ -332,7 +338,7 @@ public class SubtypeSwitcher {
             final String imiPackageName = imi.getPackageName();
             if (DBG) {
                 Log.d(TAG, "Update icons of IME: " + imiPackageName + ","
-                        + subtype.getLocale() + "," + subtype.getMode());
+                        + getSubtypeLocale(subtype) + "," + subtype.getMode());
             }
             if (subtype != null) {
                 return pm.getDrawable(imiPackageName, subtype.getIconResId(),