diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 0be886015e54cee1710b917cdb597544fcd9fc1a..4fe447e2076ddc6987eeb74559b53e5acda2fc9f 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -166,7 +166,9 @@
         <item>PC</item>
     </string-array>
     <!-- Description for generic subtype that has predefined layout.
-         The string resource name must be "subtype_generic_<layout name>". -->
+         The string resource name must be "subtype_generic_<layout name>".
+         The string resource with "No language" also must be added to strings.xml and the resource
+         name must be "subtype_no_language_<layout name>" -->
     <string name="subtype_generic_qwerty">%s (QWERTY)</string>
     <string name="subtype_generic_qwertz">%s (QWERTZ)</string>
     <string name="subtype_generic_azerty">%s (AZERTY)</string>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 93bd26867d805285fd25367ec0ea03e9f228aa6d..0d6eaee09e2c870ef09d1367f10ff7386ebc07e6 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -256,6 +256,16 @@
     <string name="subtype_no_language">No language</string>
     <!-- Description for language agnostic QWERTY keyboard subtype [CHAR LIMIT=22] -->
     <string name="subtype_no_language_qwerty">No language (QWERTY)</string>
+    <!-- Description for language agnostic QWERTZ keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_qwertz">No language (QWERTZ)</string>
+    <!-- Description for language agnostic AZERTY keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_azerty">No language (AZERTY)</string>
+    <!-- Description for language agnostic Dvorak keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_dvorak">No language (Dvorak)</string>
+    <!-- Description for language agnostic Colemak keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_colemak">No language (Colemak)</string>
+    <!-- Description for language agnostic PC QWERTY keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_pcqwerty">No language (PC)</string>
 
     <!-- Title of the preference settings for custom input styles (language and keyboard layout pairs) [CHAR LIMIT=22]-->
     <string name="custom_input_styles_title">Custom input styles</string>
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index d50d096c6a54c4e5dc8f91624a2c77605c245434..9aaaff0c4ad4dd241bd3f0cd3efbdff38cd899c5 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -20,6 +20,7 @@ import android.animation.AnimatorInflater;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -48,11 +49,13 @@ import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.ResearchLogger;
 import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.StringUtils;
 import com.android.inputmethod.latin.SubtypeLocale;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
 import com.android.inputmethod.latin.define.ProductionFlag;
 
+import java.util.Locale;
 import java.util.WeakHashMap;
 
 /**
@@ -907,7 +910,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         paint.setTextAlign(Align.CENTER);
         paint.setTypeface(Typeface.DEFAULT);
         // Estimate appropriate language name text size to fit in maxTextWidth.
-        String language = SubtypeLocale.getFullDisplayName(subtype);
+        String language = getFullDisplayName(subtype, getResources());
         int textWidth = getTextWidth(paint, language, origTextSize);
         // Assuming text width and text size are proportional to each other.
         float textSize = origTextSize * Math.min(width / textWidth, 1.0f);
@@ -919,7 +922,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
 
         final boolean useShortName;
         if (useMiddleName) {
-            language = SubtypeLocale.getMiddleDisplayName(subtype);
+            language = getMiddleDisplayName(subtype);
             textWidth = getTextWidth(paint, language, origTextSize);
             textSize = origTextSize * Math.min(width / textWidth, 1.0f);
             useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
@@ -929,7 +932,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         }
 
         if (useShortName) {
-            language = SubtypeLocale.getShortDisplayName(subtype);
+            language = getShortDisplayName(subtype);
             textWidth = getTextWidth(paint, language, origTextSize);
             textSize = origTextSize * Math.min(width / textWidth, 1.0f);
         }
@@ -975,4 +978,46 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
             drawIcon(canvas, mSpaceIcon, x, y, iconWidth, iconHeight);
         }
     }
+
+    // InputMethodSubtype's display name for spacebar text in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout | Short  Middle      Full
+    // ------ ------ - ---- --------- ----------------------
+    //  en_US qwerty F  En  English   English (US)           exception
+    //  en_GB qwerty F  En  English   English (UK)           exception
+    //  fr    azerty F  Fr  Français  Français
+    //  fr_CA qwerty F  Fr  Français  Français (Canada)
+    //  de    qwertz F  De  Deutsch   Deutsch
+    //  zz    qwerty F      QWERTY    QWERTY
+    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
+    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
+    //  en_US azerty T  En  English   English (US) (AZERTY)
+    //  zz    azerty T      AZERTY    AZERTY
+
+    // Get InputMethodSubtype's full display name in its locale.
+    static String getFullDisplayName(InputMethodSubtype subtype, Resources res) {
+        if (SubtypeLocale.isNoLanguage(subtype)) {
+            return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
+        }
+
+        return SubtypeLocale.getSubtypeDisplayName(subtype, res);
+    }
+
+    // Get InputMethodSubtype's short display name in its locale.
+    static String getShortDisplayName(InputMethodSubtype subtype) {
+        if (SubtypeLocale.isNoLanguage(subtype)) {
+            return "";
+        }
+        final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+        return StringUtils.toTitleCase(locale.getLanguage(), locale);
+    }
+
+    // Get InputMethodSubtype's middle display name in its locale.
+    static String getMiddleDisplayName(InputMethodSubtype subtype) {
+        if (SubtypeLocale.isNoLanguage(subtype)) {
+            return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
+        }
+        final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+        return StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
index b9023aef96eda7a0a6f2dae2a14f686b86584d63..06d33154f1901eed646f41527ea8237312607a56 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
@@ -42,8 +42,7 @@ public class AdditionalSubtype {
         final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
         final String filteredExtraValue = StringUtils.appendToCsvIfNotExists(
                 IS_ADDITIONAL_SUBTYPE, extraValue);
-        final int nameId = SubtypeLocale.getSubtypeNameIdFromKeyboardLayoutName(
-                keyboardLayoutSetName);
+        final int nameId = SubtypeLocale.getSubtypeNameId(localeString, keyboardLayoutSetName);
         return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
                 localeString, KEYBOARD_MODE,
                 layoutExtraValue + "," + filteredExtraValue, false, false);
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index 8ce91fd2d9baae23d14f9484329cc522f4507420..be807ab0cd3387cf603a84a8adcd3b58d125de43 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -41,7 +41,6 @@ import android.widget.ArrayAdapter;
 import android.widget.Spinner;
 import android.widget.SpinnerAdapter;
 
-import java.util.Locale;
 import java.util.TreeSet;
 
 public class AdditionalSubtypeSettings extends PreferenceFragment {
@@ -61,7 +60,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
         }
 
         public SubtypeLocaleItem(String localeString) {
-            this(localeString, getDisplayName(localeString));
+            this(localeString, SubtypeLocale.getSubtypeLocaleDisplayName(localeString));
         }
 
         @Override
@@ -73,11 +72,6 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
         public int compareTo(SubtypeLocaleItem o) {
             return first.compareTo(o.first);
         }
-
-        private static String getDisplayName(String localeString) {
-            final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
-            return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
-        }
     }
 
     static class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
@@ -185,7 +179,8 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
                 setDialogTitle(R.string.add_style);
                 setKey(KEY_NEW_SUBTYPE);
             } else {
-                final String displayName = SubtypeLocale.getFullDisplayName(subtype);
+                final String displayName = SubtypeLocale.getSubtypeDisplayName(
+                        subtype, getContext().getResources());
                 setTitle(displayName);
                 setDialogTitle(displayName);
                 setKey(KEY_PREFIX + subtype.getLocale() + "_"
diff --git a/java/src/com/android/inputmethod/latin/LocaleUtils.java b/java/src/com/android/inputmethod/latin/LocaleUtils.java
index f19c59a6a16fa80def88f08937ef69aab92da559..b938dd336f985ba1549eac42d42aa9f017307b56 100644
--- a/java/src/com/android/inputmethod/latin/LocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/LocaleUtils.java
@@ -180,13 +180,13 @@ public class LocaleUtils {
                 try {
                     if (newLocale != null && !newLocale.equals(oldLocale)) {
                         conf.locale = newLocale;
-                        res.updateConfiguration(conf, res.getDisplayMetrics());
+                        res.updateConfiguration(conf, null);
                     }
                     return job(res);
                 } finally {
                     if (newLocale != null && !newLocale.equals(oldLocale)) {
                         conf.locale = oldLocale;
-                        res.updateConfiguration(conf, res.getDisplayMetrics());
+                        res.updateConfiguration(conf, null);
                     }
                 }
             }
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 13264f7e8d63d6aad2a3e7551da8dc76147c8690..74c4aea0c4fbcb2c895e8db77b1b97d3f0fdc0db 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -300,13 +300,14 @@ public class Settings extends InputMethodSettingsFragment
         final PreferenceScreen customInputStyles =
                 (PreferenceScreen)findPreference(PREF_CUSTOM_INPUT_STYLES);
         final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
-        final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, getResources());
+        final Resources res = getResources();
+        final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, res);
         final InputMethodSubtype[] subtypes =
                 AdditionalSubtype.createAdditionalSubtypesArray(prefSubtype);
         final StringBuilder styles = new StringBuilder();
         for (final InputMethodSubtype subtype : subtypes) {
             if (styles.length() > 0) styles.append(", ");
-            styles.append(SubtypeLocale.getFullDisplayName(subtype));
+            styles.append(SubtypeLocale.getSubtypeDisplayName(subtype, res));
         }
         customInputStyles.setSummary(styles);
     }
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 88d3c3f4f5d5cf31a17da861d5644c4bf861bd3a..d10c42ccd326471b4ea24470a7f230f06cf68b0c 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -45,7 +45,10 @@ public class SubtypeLocale {
     // Keyboard layout to subtype name resource id map.
     private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap =
             new HashMap<String, Integer>();
-    private static final String SUBTYPE_RESOURCE_GENERIC_NAME_PREFIX = "string/subtype_generic_";
+    private static final String SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX =
+            "string/subtype_generic_";
+    private static final String SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX =
+            "string/subtype_no_language_";
     // Exceptional locales to display name map.
     private static final HashMap<String, String> sExceptionalDisplayNamesMap =
             new HashMap<String, String>();
@@ -64,9 +67,15 @@ public class SubtypeLocale {
         for (int i = 0; i < predefinedLayoutSet.length; i++) {
             final String layoutName = predefinedLayoutSet[i];
             sKeyboardKayoutToDisplayNameMap.put(layoutName, layoutDisplayNames[i]);
-            final String resourceName = SUBTYPE_RESOURCE_GENERIC_NAME_PREFIX + layoutName;
+            final String resourceName = SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX + layoutName;
             final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
             sKeyboardLayoutToNameIdsMap.put(layoutName, resId);
+            // Register subtype name resource id of "No language" with key "zz_<layout>"
+            final String noLanguageResName = SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX + layoutName;
+            final int noLanguageResId = res.getIdentifier(
+                    noLanguageResName, null, RESOURCE_PACKAGE_NAME);
+            final String key = getNoLanguageLayoutKey(layoutName);
+            sKeyboardLayoutToNameIdsMap.put(key, noLanguageResId);
         }
 
         final String[] exceptionalLocales = res.getStringArray(
@@ -82,65 +91,45 @@ public class SubtypeLocale {
         return sPredefinedKeyboardLayoutSet;
     }
 
-    public static int getSubtypeNameIdFromKeyboardLayoutName(String keyboardLayoutName) {
-        final Integer nameId = sKeyboardLayoutToNameIdsMap.get(keyboardLayoutName);
-        return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
+    private static final String getNoLanguageLayoutKey(String keyboardLayoutName) {
+        return NO_LANGUAGE + "_" + keyboardLayoutName;
     }
 
-    // Get InputMethodSubtype's display name in its locale.
-    //        isAdditionalSubtype (T=true, F=false)
-    // locale layout | Short  Middle      Full
-    // ------ ------ - ---- --------- -----------------
-    //  en_US qwerty F  En  English   English (US)      exception
-    //  en_GB qwerty F  En  English   English (UK)      exception
-    //  fr    azerty F  Fr  Français  Français
-    //  fr_CA qwerty F  Fr  Français  Français (Canada)
-    //  de    qwertz F  De  Deutsch   Deutsch
-    //  zz    qwerty F      QWERTY    QWERTY
-    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
-    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
-    //  en_US azerty T  En  English   English (US) (AZERTY)
-    //  zz    azerty T      AZERTY    AZERTY
-
-    // Get InputMethodSubtype's full display name in its locale.
-    public static String getFullDisplayName(InputMethodSubtype subtype) {
-        if (isNoLanguage(subtype)) {
-            return getKeyboardLayoutSetDisplayName(subtype);
-        }
-
-        final String exceptionalValue = sExceptionalDisplayNamesMap.get(subtype.getLocale());
-
-        final Locale locale = getSubtypeLocale(subtype);
-        if (AdditionalSubtype.isAdditionalSubtype(subtype)) {
-            final String language = (exceptionalValue != null) ? exceptionalValue
-                    : StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
-            final String layout = getKeyboardLayoutSetDisplayName(subtype);
-            return String.format("%s (%s)", language, layout);
-        }
+    public static int getSubtypeNameId(String localeString, String keyboardLayoutName) {
+        final String key = localeString.equals(NO_LANGUAGE)
+                ? getNoLanguageLayoutKey(keyboardLayoutName)
+                : keyboardLayoutName;
+        final Integer nameId = sKeyboardLayoutToNameIdsMap.get(key);
+        return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
+    }
 
+    public static String getSubtypeLocaleDisplayName(String localeString) {
+        final String exceptionalValue = sExceptionalDisplayNamesMap.get(localeString);
         if (exceptionalValue != null) {
             return exceptionalValue;
         }
-
+        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
         return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
     }
 
-    // Get InputMethodSubtype's middle display name in its locale.
-    public static String getMiddleDisplayName(InputMethodSubtype subtype) {
-        if (isNoLanguage(subtype)) {
-            return getKeyboardLayoutSetDisplayName(subtype);
-        }
-        final Locale locale = getSubtypeLocale(subtype);
-        return StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
-    }
-
-    // Get InputMethodSubtype's short display name in its locale.
-    public static String getShortDisplayName(InputMethodSubtype subtype) {
-        if (isNoLanguage(subtype)) {
-            return "";
-        }
-        final Locale locale = getSubtypeLocale(subtype);
-        return StringUtils.toTitleCase(locale.getLanguage(), locale);
+    // InputMethodSubtype's display name in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout |  display name
+    // ------ ------ - ----------------------
+    //  en_US qwerty F  English (US)            exception
+    //  en_GB qwerty F  English (UK)            exception
+    //  fr    azerty F  Français
+    //  fr_CA qwerty F  Français (Canada)
+    //  de    qwertz F  Deutsch
+    //  zz    qwerty F  No language (QWERTY)
+    //  fr    qwertz T  Français (QWERTZ)
+    //  de    qwerty T  Deutsch (QWERTY)
+    //  en_US azerty T  English (US) (AZERTY)
+    //  zz    azerty T  No language (AZERTY)
+
+    public static String getSubtypeDisplayName(InputMethodSubtype subtype, Resources res) {
+        final String language = getSubtypeLocaleDisplayName(subtype.getLocale());
+        return res.getString(subtype.getNameResId(), language);
     }
 
     public static boolean isNoLanguage(InputMethodSubtype subtype) {
diff --git a/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java b/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..663f7087dba546e73c00376ed63f0396b9976a3c
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 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.inputmethod.keyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.latin.AdditionalSubtype;
+import com.android.inputmethod.latin.ImfUtils;
+import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SubtypeLocale;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class SpacebarTextTests extends AndroidTestCase {
+    // Locale to subtypes list.
+    private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<InputMethodSubtype>();
+
+    private Resources mRes;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getContext();
+        mRes = context.getResources();
+        InputMethodManagerCompatWrapper.init(context);
+        SubtypeLocale.init(context);
+    }
+
+    public void testAllFullDisplayName() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
+            final String spacebarText = LatinKeyboardView.getFullDisplayName(subtype, mRes);
+            final String languageName =
+                    SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertFalse(subtypeName, spacebarText.contains(languageName));
+            } else {
+                assertTrue(subtypeName, spacebarText.contains(languageName));
+            }
+        }
+    }
+
+   public void testAllMiddleDisplayName() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
+            final String spacebarText = LatinKeyboardView.getMiddleDisplayName(subtype);
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertEquals(subtypeName,
+                        SubtypeLocale.getKeyboardLayoutSetName(subtype), spacebarText);
+            } else {
+                assertEquals(subtypeName,
+                        SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale()),
+                        spacebarText);
+            }
+        }
+    }
+
+    public void testAllShortDisplayName() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
+            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+            final String spacebarText = LatinKeyboardView.getShortDisplayName(subtype);
+            final String languageCode = StringUtils.toTitleCase(locale.getLanguage(), locale);
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertEquals(subtypeName, "", spacebarText);
+            } else {
+                assertEquals(subtypeName, languageCode, spacebarText);
+            }
+        }
+    }
+
+    // InputMethodSubtype's display name for spacebar text in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout | Short  Middle      Full
+    // ------ ------ - ---- --------- ----------------------
+    //  en_US qwerty F  En  English   English (US)           exception
+    //  en_GB qwerty F  En  English   English (UK)           exception
+    //  fr    azerty F  Fr  Français  Français
+    //  fr_CA qwerty F  Fr  Français  Français (Canada)
+    //  de    qwertz F  De  Deutsch   Deutsch
+    //  zz    qwerty F      QWERTY    QWERTY
+    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
+    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
+    //  en_US azerty T  En  English   English (US) (AZERTY)
+    //  zz    azerty T      AZERTY    AZERTY
+
+    public void testPredefinedSubtypes() {
+        final Context context = getContext();
+        final InputMethodSubtype EN_US = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.US.toString(), "qwerty");
+        final InputMethodSubtype EN_GB = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.UK.toString(), "qwerty");
+        final InputMethodSubtype FR = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.FRENCH.toString(), "azerty");
+        final InputMethodSubtype FR_CA = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.CANADA_FRENCH.toString(), "qwerty");
+        final InputMethodSubtype DE = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.GERMAN.toString(), "qwertz");
+        final InputMethodSubtype ZZ = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, SubtypeLocale.NO_LANGUAGE, "qwerty");
+
+        assertEquals("en_US", "English (US)",
+                LatinKeyboardView.getFullDisplayName(EN_US, mRes));
+        assertEquals("en_GB", "English (UK)",
+                LatinKeyboardView.getFullDisplayName(EN_GB, mRes));
+        assertEquals("fr   ", "Français",
+                LatinKeyboardView.getFullDisplayName(FR, mRes));
+        assertEquals("fr_CA", "Français (Canada)",
+                LatinKeyboardView.getFullDisplayName(FR_CA, mRes));
+        assertEquals("de   ", "Deutsch",
+                LatinKeyboardView.getFullDisplayName(DE, mRes));
+        assertEquals("zz   ", "QWERTY",
+                LatinKeyboardView.getFullDisplayName(ZZ, mRes));
+
+        assertEquals("en_US", "English",  LatinKeyboardView.getMiddleDisplayName(EN_US));
+        assertEquals("en_GB", "English",  LatinKeyboardView.getMiddleDisplayName(EN_GB));
+        assertEquals("fr   ", "Français", LatinKeyboardView.getMiddleDisplayName(FR));
+        assertEquals("fr_CA", "Français", LatinKeyboardView.getMiddleDisplayName(FR_CA));
+        assertEquals("de   ", "Deutsch",  LatinKeyboardView.getMiddleDisplayName(DE));
+        assertEquals("zz   ", "QWERTY",   LatinKeyboardView.getMiddleDisplayName(ZZ));
+
+        assertEquals("en_US", "En", LatinKeyboardView.getShortDisplayName(EN_US));
+        assertEquals("en_GB", "En", LatinKeyboardView.getShortDisplayName(EN_GB));
+        assertEquals("fr   ", "Fr", LatinKeyboardView.getShortDisplayName(FR));
+        assertEquals("fr_CA", "Fr", LatinKeyboardView.getShortDisplayName(FR_CA));
+        assertEquals("de   ", "De", LatinKeyboardView.getShortDisplayName(DE));
+        assertEquals("zz   ", "",   LatinKeyboardView.getShortDisplayName(ZZ));
+    }
+
+    public void testAdditionalSubtype() {
+        final InputMethodSubtype DE_QWERTY = AdditionalSubtype.createAdditionalSubtype(
+                Locale.GERMAN.toString(), "qwerty", null);
+        final InputMethodSubtype FR_QWERTZ = AdditionalSubtype.createAdditionalSubtype(
+                Locale.FRENCH.toString(), "qwertz", null);
+        final InputMethodSubtype US_AZERTY = AdditionalSubtype.createAdditionalSubtype(
+                Locale.US.toString(), "azerty", null);
+        final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
+                SubtypeLocale.NO_LANGUAGE, "azerty", null);
+
+        assertEquals("fr qwertz",    "Français (QWERTZ)",
+                LatinKeyboardView.getFullDisplayName(FR_QWERTZ, mRes));
+        assertEquals("de qwerty",    "Deutsch (QWERTY)",
+                LatinKeyboardView.getFullDisplayName(DE_QWERTY, mRes));
+        assertEquals("en_US azerty", "English (US) (AZERTY)",
+                LatinKeyboardView.getFullDisplayName(US_AZERTY, mRes));
+        assertEquals("zz azerty",    "AZERTY",
+                LatinKeyboardView.getFullDisplayName(ZZ_AZERTY, mRes));
+
+        assertEquals("fr qwertz",    "Français", LatinKeyboardView.getMiddleDisplayName(FR_QWERTZ));
+        assertEquals("de qwerty",    "Deutsch",  LatinKeyboardView.getMiddleDisplayName(DE_QWERTY));
+        assertEquals("en_US azerty", "English",  LatinKeyboardView.getMiddleDisplayName(US_AZERTY));
+        assertEquals("zz azerty",    "AZERTY",   LatinKeyboardView.getMiddleDisplayName(ZZ_AZERTY));
+
+        assertEquals("fr qwertz",    "Fr", LatinKeyboardView.getShortDisplayName(FR_QWERTZ));
+        assertEquals("de qwerty",    "De", LatinKeyboardView.getShortDisplayName(DE_QWERTY));
+        assertEquals("en_US azerty", "En", LatinKeyboardView.getShortDisplayName(US_AZERTY));
+        assertEquals("zz azerty",    "",  LatinKeyboardView.getShortDisplayName(ZZ_AZERTY));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
index 16b544169f17a3e819a3d304bb262e634517bd3f..5393b23acaca45a78ef9d2c4d14d57d78af5f92e 100644
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -17,10 +17,12 @@
 package com.android.inputmethod.latin;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
 
 import java.util.ArrayList;
 import java.util.Locale;
@@ -29,91 +31,47 @@ public class SubtypeLocaleTests extends AndroidTestCase {
     // Locale to subtypes list.
     private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<InputMethodSubtype>();
 
+    private Resources mRes;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         final Context context = getContext();
+        mRes = context.getResources();
         InputMethodManagerCompatWrapper.init(context);
         SubtypeLocale.init(context);
     }
 
     public void testAllFullDisplayName() {
-        final StringBuilder messages = new StringBuilder();
-        int failedCount = 0;
         for (final InputMethodSubtype subtype : mSubtypesList) {
-            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
             if (SubtypeLocale.isNoLanguage(subtype)) {
-                // This is special language name for language agnostic usage.
-                continue;
-            }
-            final String keyboardName = SubtypeLocale.getFullDisplayName(subtype);
-            final String languageName = StringUtils.toTitleCase(
-                    locale.getDisplayLanguage(locale), locale);
-            if (!keyboardName.contains(languageName)) {
-                failedCount++;
-                messages.append(String.format(
-                        "locale %s: keyboard name '%s' should contain language name '%s'\n",
-                        locale, keyboardName, languageName));
+                final String noLanguage = mRes.getString(R.string.subtype_no_language);
+                assertTrue(subtypeName, subtypeName.contains(noLanguage));
+            } else {
+                final String languageName =
+                        SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
+                assertTrue(subtypeName, subtypeName.contains(languageName));
             }
         }
-        assertEquals(messages.toString(), 0, failedCount);
     }
 
-   public void testAllMiddleDisplayName() {
-        final StringBuilder messages = new StringBuilder();
-        int failedCount = 0;
-        for (final InputMethodSubtype subtype : mSubtypesList) {
-            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
-            if (SubtypeLocale.isNoLanguage(subtype)) {
-                // This is special language name for language agnostic usage.
-                continue;
-            }
-            final String keyboardName = SubtypeLocale.getMiddleDisplayName(subtype);
-            final String languageName = StringUtils.toTitleCase(
-                    locale.getDisplayLanguage(locale), locale);
-            if (!keyboardName.equals(languageName)) {
-                failedCount++;
-                messages.append(String.format(
-                        "locale %s: keyboard name '%s' should be equals to language name '%s'\n",
-                        locale, keyboardName, languageName));
-            }
-        }
-        assertEquals(messages.toString(), 0, failedCount);
-    }
-
-    public void testAllShortDisplayName() {
-        final StringBuilder messages = new StringBuilder();
-        int failedCount = 0;
-        for (final InputMethodSubtype subtype : mSubtypesList) {
-            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
-            final String keyboardName = SubtypeLocale.getShortDisplayName(subtype);
-            final String languageCode = StringUtils.toTitleCase(locale.getLanguage(), locale);
-            if (!keyboardName.equals(languageCode)) {
-                failedCount++;
-                messages.append(String.format(
-                        "locale %s: keyboard name '%s' should be equals to language code '%s'\n",
-                        locale, keyboardName, languageCode));
-            }
-        }
-        assertEquals(messages.toString(), 0, failedCount);
-    }
-
-    // Get InputMethodSubtype's display name in its locale.
-    //            additional
-    // locale layout  Short  Middle      Full
-    // ------ ------ - ---- --------- -----------------
-    //  en_US qwerty F  En  English   English (US)      exception
-    //  en_GB qwerty F  En  English   English (UK)      exception
-    //  fr    azerty F  Fr  Français  Français
-    //  fr_CA qwerty F  Fr  Français  Français (Canada)
-    //  de    qwertz F  De  Deutsch   Deutsch
-    //  zz    qwerty F      QWERTY    QWERTY
-    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
-    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
-    //  en_US azerty T  En  English   English (US) (AZERTY)
-    //  zz    azerty T      AZERTY    AZERTY
-
-    public void testSampleSubtypes() {
+    // InputMethodSubtype's display name in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout |  display name
+    // ------ ------ - ----------------------
+    //  en_US qwerty F  English (US)            exception
+    //  en_GB qwerty F  English (UK)            exception
+    //  fr    azerty F  Français
+    //  fr_CA qwerty F  Français (Canada)
+    //  de    qwertz F  Deutsch
+    //  zz    qwerty F  No language (QWERTY)
+    //  fr    qwertz T  Français (QWERTZ)
+    //  de    qwerty T  Deutsch (QWERTY)
+    //  en_US azerty T  English (US) (AZERTY)
+    //  zz    azerty T  No language (AZERTY)
+
+    public void testPredefinedSubtypes() {
         final Context context = getContext();
         final InputMethodSubtype EN_US = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, Locale.US.toString(), "qwerty");
@@ -128,13 +86,6 @@ public class SubtypeLocaleTests extends AndroidTestCase {
         final InputMethodSubtype ZZ = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, SubtypeLocale.NO_LANGUAGE, "qwerty");
 
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(EN_US));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(EN_GB));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(FR));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(FR_CA));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(DE));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(ZZ));
-
         assertEquals("en_US", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_US));
         assertEquals("en_GB", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_GB));
         assertEquals("fr   ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(FR));
@@ -142,26 +93,18 @@ public class SubtypeLocaleTests extends AndroidTestCase {
         assertEquals("de   ", "qwertz", SubtypeLocale.getKeyboardLayoutSetName(DE));
         assertEquals("zz   ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
 
-        assertEquals("en_US", "English (US)",      SubtypeLocale.getFullDisplayName(EN_US));
-        assertEquals("en_GB", "English (UK)",      SubtypeLocale.getFullDisplayName(EN_GB));
-        assertEquals("fr   ", "Français",          SubtypeLocale.getFullDisplayName(FR));
-        assertEquals("fr_CA", "Français (Canada)", SubtypeLocale.getFullDisplayName(FR_CA));
-        assertEquals("de   ", "Deutsch",           SubtypeLocale.getFullDisplayName(DE));
-        assertEquals("zz   ", "QWERTY",            SubtypeLocale.getFullDisplayName(ZZ));
-
-        assertEquals("en_US", "English",  SubtypeLocale.getMiddleDisplayName(EN_US));
-        assertEquals("en_GB", "English",  SubtypeLocale.getMiddleDisplayName(EN_GB));
-        assertEquals("fr   ", "Français", SubtypeLocale.getMiddleDisplayName(FR));
-        assertEquals("fr_CA", "Français", SubtypeLocale.getMiddleDisplayName(FR_CA));
-        assertEquals("de   ", "Deutsch",  SubtypeLocale.getMiddleDisplayName(DE));
-        assertEquals("zz   ", "QWERTY",   SubtypeLocale.getMiddleDisplayName(ZZ));
-
-        assertEquals("en_US", "En", SubtypeLocale.getShortDisplayName(EN_US));
-        assertEquals("en_GB", "En", SubtypeLocale.getShortDisplayName(EN_GB));
-        assertEquals("fr   ", "Fr", SubtypeLocale.getShortDisplayName(FR));
-        assertEquals("fr_CA", "Fr", SubtypeLocale.getShortDisplayName(FR_CA));
-        assertEquals("de   ", "De", SubtypeLocale.getShortDisplayName(DE));
-        assertEquals("zz   ", "", SubtypeLocale.getShortDisplayName(ZZ));
+        assertEquals("en_US", "English (US)",
+                SubtypeLocale.getSubtypeDisplayName(EN_US, mRes));
+        assertEquals("en_GB", "English (UK)",
+                SubtypeLocale.getSubtypeDisplayName(EN_GB, mRes));
+        assertEquals("fr   ", "Français",
+                SubtypeLocale.getSubtypeDisplayName(FR, mRes));
+        assertEquals("fr_CA", "Français (Canada)",
+                SubtypeLocale.getSubtypeDisplayName(FR_CA, mRes));
+        assertEquals("de   ", "Deutsch",
+                SubtypeLocale.getSubtypeDisplayName(DE, mRes));
+        assertEquals("zz   ", "No language (QWERTY)",
+                SubtypeLocale.getSubtypeDisplayName(ZZ, mRes));
     }
 
     public void testAdditionalSubtype() {
@@ -174,28 +117,36 @@ public class SubtypeLocaleTests extends AndroidTestCase {
         final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
                 SubtypeLocale.NO_LANGUAGE, "azerty", null);
 
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(FR_QWERTZ));
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(DE_QWERTY));
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(US_AZERTY));
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(ZZ_AZERTY));
-
         assertEquals("fr qwertz",    "Français (QWERTZ)",
-                SubtypeLocale.getFullDisplayName(FR_QWERTZ));
+                SubtypeLocale.getSubtypeDisplayName(FR_QWERTZ, mRes));
         assertEquals("de qwerty",    "Deutsch (QWERTY)",
-                SubtypeLocale.getFullDisplayName(DE_QWERTY));
+                SubtypeLocale.getSubtypeDisplayName(DE_QWERTY, mRes));
         assertEquals("en_US azerty", "English (US) (AZERTY)",
-                SubtypeLocale.getFullDisplayName(US_AZERTY));
-        assertEquals("zz azerty",    "AZERTY",
-                SubtypeLocale.getFullDisplayName(ZZ_AZERTY));
-
-        assertEquals("fr qwertz",    "Français", SubtypeLocale.getMiddleDisplayName(FR_QWERTZ));
-        assertEquals("de qwerty",    "Deutsch",  SubtypeLocale.getMiddleDisplayName(DE_QWERTY));
-        assertEquals("en_US azerty", "English",  SubtypeLocale.getMiddleDisplayName(US_AZERTY));
-        assertEquals("zz azerty",    "AZERTY",   SubtypeLocale.getMiddleDisplayName(ZZ_AZERTY));
-
-        assertEquals("fr qwertz",    "Fr", SubtypeLocale.getShortDisplayName(FR_QWERTZ));
-        assertEquals("de qwerty",    "De", SubtypeLocale.getShortDisplayName(DE_QWERTY));
-        assertEquals("en_US azerty", "En", SubtypeLocale.getShortDisplayName(US_AZERTY));
-        assertEquals("zz azerty",    "", SubtypeLocale.getShortDisplayName(ZZ_AZERTY));
+                SubtypeLocale.getSubtypeDisplayName(US_AZERTY, mRes));
+        assertEquals("zz azerty",    "No language (AZERTY)",
+                SubtypeLocale.getSubtypeDisplayName(ZZ_AZERTY, mRes));
+    }
+
+    public void testNoLanguageInFrench() {
+        final Context context = getContext();
+        final InputMethodSubtype ZZ = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, SubtypeLocale.NO_LANGUAGE, "qwerty");
+        final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
+                SubtypeLocale.NO_LANGUAGE, "azerty", null);
+
+        final RunInLocale<Void> tests = new RunInLocale<Void>() {
+            @Override
+            protected Void job(Resources res) {
+                assertEquals("zz   ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
+                assertEquals("zz   ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ_AZERTY));
+
+                assertEquals("zz   ",     "Pas de langue (QWERTY)",
+                        SubtypeLocale.getSubtypeDisplayName(ZZ, res));
+                assertEquals("zz azerty", "Pas de langue (AZERTY)",
+                        SubtypeLocale.getSubtypeDisplayName(ZZ_AZERTY, res));
+                return null;
+            }
+        };
+        tests.runInLocale(mRes, Locale.FRENCH);
     }
 }