Use "No language (QWERTY)" for language agnostic QWERTY keyboard name
Bug: 6010147
Change-Id: I401c2e3fcd639c0e1a03e64489a0d792810caa18
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 68a8cab..9c8bd3c 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -156,22 +156,20 @@
<string-array name="subtype_locale_exception_keys">
<item>en_US</item>
<item>en_GB</item>
- <item>de_QY</item>
- <item>zz_QY</item>
+ <item>*_QY</item>
+ <item>QY</item>
</string-array>
<string-array name="subtype_locale_exception_values">
<item>English (US)</item>
<item>English (UK)</item>
<item>@string/subtype_generic_qwerty</item>
- <item>@string/subtype_qwerty</item>
+ <item>QWERTY</item>
</string-array>
<!-- Generic subtype label -->
<string name="subtype_generic">%s</string>
<!-- Description for generic QWERTY keyboard subtype -->
<string name="subtype_generic_qwerty">%s (QWERTY)</string>
- <!-- Description for language agnostic QWERTY keyboard subtype -->
- <string name="subtype_qwerty">QWERTY</string>
<!-- dictionary pack package name /settings activity (for shared prefs and settings) -->
<string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 4f038e1..a22c68c 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -252,6 +252,8 @@
<string name="subtype_en_GB">English (UK)</string>
<!-- Description for English (United States) keyboard subtype [CHAR LIMIT=22] -->
<string name="subtype_en_US">English (US)</string>
+ <!-- Description for language agnostic QWERTY keyboard subtype [CHAR LIMIT=22] -->
+ <string name="subtype_no_language_qwerty">No language (QWERTY)</string>
<!-- Title of an option for usability study mode -->
<string name="prefs_usability_study_mode">Usability study mode</string>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 7a21a85..e43fb32 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -312,7 +312,7 @@
android:imeSubtypeExtraValue="AsciiCapable"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
- android:label="@string/subtype_qwerty"
+ android:label="@string/subtype_no_language_qwerty"
android:imeSubtypeLocale="zz_QY"
android:imeSubtypeMode="keyboard"
android:imeSubtypeExtraValue="AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable"
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index e2af971..2689e6e 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -47,7 +47,7 @@
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.SubtypeUtils;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
@@ -926,7 +926,7 @@
paint.setTextAlign(Align.CENTER);
paint.setTypeface(Typeface.DEFAULT);
// Estimate appropriate language name text size to fit in maxTextWidth.
- String language = StringUtils.getFullDisplayName(locale, true);
+ String language = SubtypeLocale.getFullDisplayName(locale);
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);
@@ -938,7 +938,7 @@
final boolean useShortName;
if (useMiddleName) {
- language = StringUtils.getMiddleDisplayLanguage(locale);
+ language = SubtypeLocale.getMiddleDisplayName(locale);
textWidth = getTextWidth(paint, language, origTextSize);
textSize = origTextSize * Math.min(width / textWidth, 1.0f);
useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
@@ -948,7 +948,7 @@
}
if (useShortName) {
- language = StringUtils.getShortDisplayLanguage(locale);
+ language = SubtypeLocale.getShortDisplayName(locale);
textWidth = getTextWidth(paint, language, origTextSize);
textSize = origTextSize * Math.min(width / textWidth, 1.0f);
}
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index 7b34cae..7000e46 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -22,7 +22,6 @@
import com.android.inputmethod.keyboard.Keyboard;
import java.util.ArrayList;
-import java.util.Locale;
public class StringUtils {
private StringUtils() {
@@ -150,41 +149,4 @@
i++;
}
}
-
- public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) {
- if (returnsNameInThisLocale) {
- return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale);
- } else {
- return toTitleCase(locale.getDisplayName(), locale);
- }
- }
-
- public static String getDisplayLanguage(Locale locale) {
- return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale);
- }
-
- public static String getMiddleDisplayLanguage(Locale locale) {
- return toTitleCase((LocaleUtils.constructLocaleFromString(
- locale.getLanguage()).getDisplayLanguage(locale)), locale);
- }
-
- public static String getShortDisplayLanguage(Locale locale) {
- return toTitleCase(locale.getLanguage(), locale);
- }
-
- public static String toTitleCase(String s, Locale locale) {
- if (s.length() <= 1) {
- // TODO: is this really correct? Shouldn't this be s.toUpperCase()?
- return s;
- }
- // TODO: fix the bugs below
- // - This does not work for Greek, because it returns upper case instead of title case.
- // - It does not work for Serbian, because it fails to account for the "lj" character,
- // which should be "Lj" in title case and "LJ" in upper case.
- // - It does not work for Dutch, because it fails to account for the "ij" digraph, which
- // are two different characters but both should be capitalized as "IJ" as if they were
- // a single letter.
- // - It also does not work with unicode surrogate code points.
- return s.toUpperCase(locale).charAt(0) + s.substring(1);
- }
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 66c13bd..40051a7 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -22,6 +22,13 @@
import java.util.Locale;
public class SubtypeLocale {
+ // Special language code to represent "no language".
+ /* package for test */ static final String NO_LANGUAGE = "zz";
+ // Special country code to represent "QWERTY".
+ /* package for test */ static final String QWERTY = "QY";
+
+ public static final Locale LOCALE_NO_LANGUAGE_QWERTY = new Locale(NO_LANGUAGE, QWERTY);
+
private static String[] sExceptionKeys;
private static String[] sExceptionValues;
@@ -35,18 +42,82 @@
sExceptionValues = res.getStringArray(R.array.subtype_locale_exception_values);
}
- public static String getFullDisplayName(Locale locale) {
- final String localeCode = locale.toString();
+ private static String lookupExceptionalLocale(String key) {
for (int index = 0; index < sExceptionKeys.length; index++) {
- if (sExceptionKeys[index].equals(localeCode)) {
- final String value = sExceptionValues[index];
- if (value.indexOf("%s") >= 0) {
- final String languageName = locale.getDisplayLanguage(locale);
- return String.format(value, languageName);
- }
- return value;
+ if (sExceptionKeys[index].equals(key)) {
+ return sExceptionValues[index];
}
}
- return locale.getDisplayName(locale);
+ return null;
+ }
+
+ // Get Locale's full display name in its locale.
+ // For example:
+ // "fr_CH" is converted to "Français (Suisse)".
+ // "de_QY" is converted to "Deutsche (QWERTY)". (Any locale that has country code "QY")
+ // "zz_QY" is converted to "QWERTY". (The language code "zz" means "No language", thus just
+ // ends up with the keyboard layout name.)
+ public static String getFullDisplayName(Locale locale) {
+ final String key;
+ if (locale.getLanguage().equals(NO_LANGUAGE)) {
+ key = locale.getCountry();
+ } else if (locale.getCountry().equals(QWERTY)) {
+ key = "*_" + QWERTY;
+ } else {
+ key = locale.toString();
+ }
+ final String value = lookupExceptionalLocale(key);
+ if (value == null) {
+ return toTitleCase(locale.getDisplayName(locale), locale);
+ }
+ if (value.indexOf("%s") >= 0) {
+ final String languageName = toTitleCase(locale.getDisplayLanguage(locale), locale);
+ return String.format(value, languageName);
+ }
+ return value;
+ }
+
+ // Get Locale's middle display name in its locale.
+ // For example:
+ // "fr_CH" is converted to "Français".
+ // "de_QY" is converted to "Deutsche". (Any locale that has country code "QY")
+ // "zz_QY" is converted to "QWERTY". (The language code "zz" means "No language", thus just
+ // ends up with the keyboard layout name.)
+ public static String getMiddleDisplayName(Locale locale) {
+ if (NO_LANGUAGE.equals(locale.getLanguage())) {
+ return lookupExceptionalLocale(locale.getCountry());
+ } else {
+ return toTitleCase(locale.getDisplayLanguage(locale), locale);
+ }
+ }
+
+ // Get Locale's short display name in its locale.
+ // For example:
+ // "fr_CH" is converted to "Fr".
+ // "de_QY" is converted to "De". (Any locale that has country code "QY")
+ // "zz_QY" is converter to "QY". (The language code "zz" means "No language", thus just ends
+ // up with the keyboard layout name.)
+ public static String getShortDisplayName(Locale locale) {
+ if (NO_LANGUAGE.equals(locale.getLanguage())) {
+ return locale.getCountry();
+ } else {
+ return toTitleCase(locale.getLanguage(), locale);
+ }
+ }
+
+ public static String toTitleCase(String s, Locale locale) {
+ if (s.length() <= 1) {
+ // TODO: is this really correct? Shouldn't this be s.toUpperCase()?
+ return s;
+ }
+ // TODO: fix the bugs below
+ // - This does not work for Greek, because it returns upper case instead of title case.
+ // - It does not work for Serbian, because it fails to account for the "lj" character,
+ // which should be "Lj" in title case and "LJ" in upper case.
+ // - It does not work for Dutch, because it fails to account for the "ij" digraph, which
+ // are two different characters but both should be capitalized as "IJ" as if they were
+ // a single letter.
+ // - It also does not work with unicode surrogate code points.
+ return s.toUpperCase(locale).charAt(0) + s.substring(1);
}
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index e353644..c2dafcf 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -420,10 +420,6 @@
return KEYBOARD_MODE.equals(getCurrentSubtypeMode());
}
- public String getInputLanguageName() {
- return StringUtils.getDisplayLanguage(getInputLocale());
- }
-
/////////////////////////////
// Other utility functions //
/////////////////////////////
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 7b13e40..cd01bb1 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -37,6 +37,7 @@
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SubtypeLocale;
import com.android.inputmethod.latin.SynchronouslyLoadedContactsDictionary;
import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary;
import com.android.inputmethod.latin.WhitelistDictionary;
@@ -325,8 +326,8 @@
} else if (CAPITALIZE_FIRST == capitalizeType) {
for (int i = 0; i < mSuggestions.size(); ++i) {
// Likewise
- mSuggestions.set(i, StringUtils.toTitleCase(mSuggestions.get(i).toString(),
- locale));
+ mSuggestions.set(i, SubtypeLocale.toTitleCase(
+ mSuggestions.get(i).toString(), locale));
}
}
// This returns a String[], while toArray() returns an Object[] which cannot be cast
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
index 089fdc5..6180ff5 100644
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -23,11 +23,14 @@
import android.view.inputmethod.InputMethodSubtype;
import java.util.ArrayList;
-import java.util.List;
import java.util.Locale;
public class SubtypeLocaleTests extends AndroidTestCase {
- private List<InputMethodSubtype> mKeyboardSubtypes;
+ private static final Locale LOCALE_zz_QY = SubtypeLocale.LOCALE_NO_LANGUAGE_QWERTY;
+ private static final Locale LOCALE_de_QY =
+ new Locale(Locale.GERMAN.getLanguage(), SubtypeLocale.QWERTY);
+
+ private ArrayList<InputMethodSubtype> mSubtypesList;
@Override
protected void setUp() throws Exception {
@@ -42,46 +45,111 @@
Context.INPUT_METHOD_SERVICE);
for (final InputMethodInfo imi : imm.getInputMethodList()) {
if (imi.getPackageName().equals(packageName)) {
- mKeyboardSubtypes = new ArrayList<InputMethodSubtype>();
+ mSubtypesList = new ArrayList<InputMethodSubtype>();
final int subtypeCount = imi.getSubtypeCount();
- for (int i = 0; i < subtypeCount; ++i) {
- InputMethodSubtype subtype = imi.getSubtypeAt(i);
- if (subtype.getMode().equals("keyboard")) {
- mKeyboardSubtypes.add(subtype);
- }
+ for (int i = 0; i < subtypeCount; i++) {
+ final InputMethodSubtype ims = imi.getSubtypeAt(i);
+ mSubtypesList.add(ims);
}
break;
}
}
- assertNotNull("Can not find input method " + packageName, mKeyboardSubtypes);
- assertTrue("Can not find keyboard subtype", mKeyboardSubtypes.size() > 0);
+ assertNotNull("Can not find input method " + packageName, mSubtypesList);
+ assertTrue("Can not find keyboard subtype", mSubtypesList.size() > 0);
}
- public void testSubtypeLocale() {
+ private static Locale getSubtypeLocale(InputMethodSubtype subtype) {
+ return LocaleUtils.constructLocaleFromString(subtype.getLocale());
+ }
+
+ private static Locale getKeyboardLocale(InputMethodSubtype subtype) {
+ final String subtypeLocaleString = subtype.containsExtraValueKey(
+ LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE)
+ ? subtype.getExtraValueOf(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE)
+ : subtype.getLocale();
+ return LocaleUtils.constructLocaleFromString(subtypeLocaleString);
+ }
+
+ public void testFullDisplayName() {
final StringBuilder messages = new StringBuilder();
int failedCount = 0;
- for (final InputMethodSubtype subtype : mKeyboardSubtypes) {
- final Locale locale = LocaleUtils.constructLocaleFromString(subtype.getLocale());
- if (locale.getLanguage().equals("zz")) {
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final Locale locale = getKeyboardLocale(subtype);
+ if (locale.getLanguage().equals(SubtypeLocale.NO_LANGUAGE)) {
// This is special language name for language agnostic usage.
continue;
}
- final String subtypeLocaleString =
- subtype.containsExtraValueKey(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE)
- ? subtype.getExtraValueOf(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE)
- : subtype.getLocale();
- final Locale subtypeLocale = LocaleUtils.constructLocaleFromString(subtypeLocaleString);
- // The subtype name in its locale. For example 'English (US)' or 'Deutsch (QWERTY)'.
- final String subtypeName = SubtypeLocale.getFullDisplayName(subtypeLocale);
- // The locale language name in its locale.
- final String languageName = locale.getDisplayLanguage(locale);
- if (!subtypeName.contains(languageName)) {
+ final String keyboardName = SubtypeLocale.getFullDisplayName(locale);
+ final String languageName = SubtypeLocale.toTitleCase(
+ locale.getDisplayLanguage(locale), locale);
+ if (!keyboardName.contains(languageName)) {
failedCount++;
messages.append(String.format(
- "subtype name is '%s' and should contain locale '%s' language name '%s'\n",
- subtypeName, subtypeLocale, languageName));
+ "locale %s: keyboard name '%s' should contain language name '%s'\n",
+ locale, keyboardName, languageName));
}
}
assertEquals(messages.toString(), 0, failedCount);
}
+
+ public void testFullDisplayNameNoLanguage() {
+ assertEquals("zz_QY", "QWERTY", SubtypeLocale.getFullDisplayName(LOCALE_zz_QY));
+
+ final String de_QY = SubtypeLocale.getFullDisplayName(LOCALE_de_QY);
+ assertTrue("de_QY", de_QY.contains("(QWERTY"));
+ assertTrue("de_QY", de_QY.contains(Locale.GERMAN.getDisplayLanguage(Locale.GERMAN)));
+ }
+
+ public void testMiddleDisplayName() {
+ final StringBuilder messages = new StringBuilder();
+ int failedCount = 0;
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final Locale locale = getKeyboardLocale(subtype);
+ if (locale.getLanguage().equals(SubtypeLocale.NO_LANGUAGE)) {
+ // This is special language name for language agnostic usage.
+ continue;
+ }
+ final String keyboardName = SubtypeLocale.getMiddleDisplayName(locale);
+ final String languageName = SubtypeLocale.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 testMiddleDisplayNameNoLanguage() {
+ assertEquals("zz_QY", "QWERTY", SubtypeLocale.getMiddleDisplayName(LOCALE_zz_QY));
+ assertEquals("de_QY", "Deutsch", SubtypeLocale.getMiddleDisplayName(LOCALE_de_QY));
+ }
+
+ public void testShortDisplayName() {
+ final StringBuilder messages = new StringBuilder();
+ int failedCount = 0;
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final Locale locale = getKeyboardLocale(subtype);
+ if (locale.getCountry().equals(SubtypeLocale.QWERTY)) {
+ // This is special country code for QWERTY keyboard.
+ continue;
+ }
+ final String keyboardName = SubtypeLocale.getShortDisplayName(locale);
+ final String languageCode = SubtypeLocale.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);
+ }
+
+ public void testShortDisplayNameNoLanguage() {
+ assertEquals("zz_QY", "QY", SubtypeLocale.getShortDisplayName(LOCALE_zz_QY));
+ assertEquals("de_QY", "De", SubtypeLocale.getShortDisplayName(LOCALE_de_QY));
+ }
}