Merge "Import translations. DO NOT MERGE"
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 937a799..a4e2d29 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -365,18 +365,12 @@
          (Compact) can be an abbreviation to fit in the CHAR LIMIT.
          TODO: Remove translatable=false once we are settled down with the naming. -->
     <string name="subtype_generic_compact" translatable="false"><xliff:g id="LANGUAGE_NAME" example="Hindi">%s</xliff:g> (Compact)</string>
-    <!-- TODO: Uncomment once we can handle IETF language tag with script name specified.
-         Description for Serbian Cyrillic keyboard subtype [CHAR LIMIT=25]
-         (Cyrillic) can be an abbreviation to fit in the CHAR LIMIT.
-    <string name="subtype_serbian_cyrillic">Serbian (Cyrillic)</string>
-         Description for Serbian Latin keyboard subtype [CHAR LIMIT=25]
-         (Latin) can be an abbreviation to fit in the CHAR LIMIT.
-    <string name="subtype_serbian_latin">Serbian (Latin)</string>
-         Description for Serbian Latin keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
-         (Latin) can be an abbreviation to fit in the CHAR LIMIT.
-         This should be identical to subtype_serbian_latin aside from the trailing (%s).
-    <string name="subtype_with_layout_sr-Latn">Serbian (Latin) (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string>
-    -->
+    <!-- Description for "LANGUAGE_NAME" (Cyrillic) keyboard subtype [CHAR LIMIT=25]
+         (Cyrillic) can be an abbreviation to fit in the CHAR LIMIT. -->
+    <string name="subtype_generic_cyrillic"><xliff:g id="LANGUAGE_NAME" example="Serbian">%s</xliff:g> (Cyrillic)</string>
+    <!-- Description for "LANGUAGE_NAME" (Latin) keyboard subtype [CHAR LIMIT=25]
+         (Latin) can be an abbreviation to fit in the CHAR LIMIT. -->
+    <string name="subtype_generic_latin"><xliff:g id="LANGUAGE_NAME" example="Serbian">%s</xliff:g> (Latin)</string>
     <!-- This string is displayed in a language list that allows to choose a language for
 suggestions in a software keyboard. This setting won't give suggestions in any particular
 language, hence "No language".
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 6d8f787..594378f 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -57,6 +57,7 @@
     in: Indonesian/qwerty    # "id" is the official language code of Indonesian.
     is: Icelandic/qwerty
     it: Italian/qwerty
+    it_CH: Italian (Switzerland)/swiss
     iw: Hebrew/hebrew        # "he" is the official language code of Hebrew.
     ka_GE: Georgian (Georgia)/georgian
     kk: Kazakh/east_slavic
@@ -385,6 +386,14 @@
             android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable"
             android:isAsciiCapable="true"
     />
+    <subtype android:icon="@drawable/ic_ime_switcher_dark"
+            android:label="@string/subtype_generic"
+            android:subtypeId="0xd914fe1a"
+            android:imeSubtypeLocale="it_CH"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="KeyboardLayoutSet=swiss,AsciiCapable,EmojiCapable"
+            android:isAsciiCapable="true"
+    />
     <!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
diff --git a/java/res/xml/rowkeys_greek1.xml b/java/res/xml/rowkeys_greek1.xml
index c5033d0..6d76779 100644
--- a/java/res/xml/rowkeys_greek1.xml
+++ b/java/res/xml/rowkeys_greek1.xml
@@ -69,7 +69,7 @@
         latin:keySpec="&#x03B5;"
         latin:keyHintLabel="3"
         latin:additionalMoreKeys="3"
-        latin:moreKeys="&#x03AD;" />
+        latin:moreKeys="&#x03AD;,%" />
     <!-- U+03C1: "ρ" GREEK SMALL LETTER RHO -->
     <Key
         latin:keySpec="&#x03C1;"
@@ -88,7 +88,7 @@
         latin:keySpec="&#x03C5;"
         latin:keyHintLabel="6"
         latin:additionalMoreKeys="6"
-        latin:moreKeys="&#x03CD;,&#x03CB;,&#x03B0;" />
+        latin:moreKeys="&#x03CD;,%,&#x03CB;,&#x03B0;" />
     <!-- U+03B8: "θ" GREEK SMALL LETTER THETA -->
     <Key
         latin:keySpec="&#x03B8;"
@@ -102,14 +102,14 @@
         latin:keySpec="&#x03B9;"
         latin:keyHintLabel="8"
         latin:additionalMoreKeys="8"
-        latin:moreKeys="&#x03AF;,&#x03CA;,&#x0390;" />
+        latin:moreKeys="&#x03AF;,%,&#x03CA;,&#x0390;" />
     <!-- U+03BF: "ο" GREEK SMALL LETTER OMICRON
          U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS -->
     <Key
         latin:keySpec="&#x03BF;"
         latin:keyHintLabel="9"
         latin:additionalMoreKeys="9"
-        latin:moreKeys="&#x03CC;" />
+        latin:moreKeys="&#x03CC;,%" />
     <!-- U+03C0: "π" GREEK SMALL LETTER PI -->
     <Key
         latin:keySpec="&#x03C0;"
diff --git a/java/src/com/android/inputmethod/compat/LooperCompatUtils.java b/java/src/com/android/inputmethod/compat/LooperCompatUtils.java
new file mode 100644
index 0000000..d647dbb
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/LooperCompatUtils.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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.compat;
+
+import android.os.Looper;
+
+import java.lang.reflect.Method;
+
+/**
+ * Helper to call Looper#quitSafely, which was introduced in API
+ * level 18 (Build.VERSION_CODES.JELLY_BEAN_MR2).
+ *
+ * In unit tests, we create lots of instances of LatinIME, which means we need to clean up
+ * some Loopers lest we leak file descriptors. In normal use on a device though, this is never
+ * necessary (although it does not hurt).
+ */
+public final class LooperCompatUtils {
+    private static final Method METHOD_quitSafely = CompatUtils.getMethod(
+            Looper.class, "quitSafely");
+
+    public static void quitSafely(final Looper looper) {
+        if (null != METHOD_quitSafely) {
+            CompatUtils.invoke(looper, null /* default return value */, METHOD_quitSafely);
+        } else {
+            looper.quit();
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 2e4a090..949f037 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -297,12 +297,19 @@
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
+    // TODO[IL]: merge the two following methods; remove the one without args.
     @Override
     public void requestUpdatingShiftState() {
         mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState(),
                 mLatinIME.getCurrentRecapitalizeState());
     }
 
+    // Future method for requesting an updating to the shift state.
+    public void requestUpdatingShiftState(final int currentAutoCapsState,
+            final int currentRecapitalizeState) {
+        mState.onUpdateShiftState(currentAutoCapsState, currentRecapitalizeState);
+    }
+
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void startDoubleTapShiftKeyTimer() {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index f0356df..37514be 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -141,43 +141,43 @@
         /*  51: 4 */ "additional_morekeys_symbols_8",
         /*  52: 4 */ "additional_morekeys_symbols_9",
         /*  53: 4 */ "additional_morekeys_symbols_0",
-        /*  54: 3 */ "morekeys_punctuation",
-        /*  55: 3 */ "morekeys_star",
-        /*  56: 3 */ "keyspec_left_parenthesis",
-        /*  57: 3 */ "keyspec_right_parenthesis",
-        /*  58: 3 */ "keyspec_left_square_bracket",
-        /*  59: 3 */ "keyspec_right_square_bracket",
-        /*  60: 3 */ "keyspec_left_curly_bracket",
-        /*  61: 3 */ "keyspec_right_curly_bracket",
-        /*  62: 3 */ "keyspec_less_than",
-        /*  63: 3 */ "keyspec_greater_than",
-        /*  64: 3 */ "keyspec_less_than_equal",
-        /*  65: 3 */ "keyspec_greater_than_equal",
-        /*  66: 3 */ "keyspec_left_double_angle_quote",
-        /*  67: 3 */ "keyspec_right_double_angle_quote",
-        /*  68: 3 */ "keyspec_left_single_angle_quote",
-        /*  69: 3 */ "keyspec_right_single_angle_quote",
-        /*  70: 3 */ "keyspec_tablet_comma",
-        /*  71: 3 */ "morekeys_tablet_period",
-        /*  72: 3 */ "morekeys_question",
-        /*  73: 2 */ "morekeys_h",
-        /*  74: 2 */ "morekeys_w",
-        /*  75: 2 */ "morekeys_east_slavic_row2_2",
-        /*  76: 2 */ "morekeys_cyrillic_u",
-        /*  77: 2 */ "morekeys_cyrillic_en",
-        /*  78: 2 */ "morekeys_cyrillic_ghe",
-        /*  79: 2 */ "morekeys_cyrillic_o",
-        /*  80: 2 */ "morekeys_cyrillic_i",
-        /*  81: 2 */ "keyspec_south_slavic_row1_6",
-        /*  82: 2 */ "keyspec_south_slavic_row2_11",
-        /*  83: 2 */ "keyspec_south_slavic_row3_1",
-        /*  84: 2 */ "keyspec_south_slavic_row3_8",
-        /*  85: 2 */ "keyspec_swiss_row1_11",
-        /*  86: 2 */ "keyspec_swiss_row2_10",
-        /*  87: 2 */ "keyspec_swiss_row2_11",
-        /*  88: 2 */ "morekeys_swiss_row1_11",
-        /*  89: 2 */ "morekeys_swiss_row2_10",
-        /*  90: 2 */ "morekeys_swiss_row2_11",
+        /*  54: 3 */ "keyspec_swiss_row1_11",
+        /*  55: 3 */ "keyspec_swiss_row2_10",
+        /*  56: 3 */ "keyspec_swiss_row2_11",
+        /*  57: 3 */ "morekeys_swiss_row1_11",
+        /*  58: 3 */ "morekeys_swiss_row2_10",
+        /*  59: 3 */ "morekeys_swiss_row2_11",
+        /*  60: 3 */ "morekeys_punctuation",
+        /*  61: 3 */ "morekeys_star",
+        /*  62: 3 */ "keyspec_left_parenthesis",
+        /*  63: 3 */ "keyspec_right_parenthesis",
+        /*  64: 3 */ "keyspec_left_square_bracket",
+        /*  65: 3 */ "keyspec_right_square_bracket",
+        /*  66: 3 */ "keyspec_left_curly_bracket",
+        /*  67: 3 */ "keyspec_right_curly_bracket",
+        /*  68: 3 */ "keyspec_less_than",
+        /*  69: 3 */ "keyspec_greater_than",
+        /*  70: 3 */ "keyspec_less_than_equal",
+        /*  71: 3 */ "keyspec_greater_than_equal",
+        /*  72: 3 */ "keyspec_left_double_angle_quote",
+        /*  73: 3 */ "keyspec_right_double_angle_quote",
+        /*  74: 3 */ "keyspec_left_single_angle_quote",
+        /*  75: 3 */ "keyspec_right_single_angle_quote",
+        /*  76: 3 */ "keyspec_tablet_comma",
+        /*  77: 3 */ "morekeys_tablet_period",
+        /*  78: 3 */ "morekeys_question",
+        /*  79: 2 */ "morekeys_h",
+        /*  80: 2 */ "morekeys_w",
+        /*  81: 2 */ "morekeys_east_slavic_row2_2",
+        /*  82: 2 */ "morekeys_cyrillic_u",
+        /*  83: 2 */ "morekeys_cyrillic_en",
+        /*  84: 2 */ "morekeys_cyrillic_ghe",
+        /*  85: 2 */ "morekeys_cyrillic_o",
+        /*  86: 2 */ "morekeys_cyrillic_i",
+        /*  87: 2 */ "keyspec_south_slavic_row1_6",
+        /*  88: 2 */ "keyspec_south_slavic_row2_11",
+        /*  89: 2 */ "keyspec_south_slavic_row3_1",
+        /*  90: 2 */ "keyspec_south_slavic_row3_8",
         /*  91: 2 */ "keyspec_spanish_row2_10",
         /*  92: 2 */ "morekeys_bullet",
         /*  93: 2 */ "morekeys_left_parenthesis",
@@ -291,8 +291,9 @@
         // Label for "switch to symbols" key.
         /* keylabel_to_symbol */ "?123",
         /* additional_morekeys_symbols_1 ~ */
-        EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
-        /* ~ additional_morekeys_symbols_0 */
+        EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
+        EMPTY, EMPTY, EMPTY,
+        /* ~ morekeys_swiss_row2_11 */
         /* morekeys_punctuation */ "!autoColumnOrder!8,\\,,?,!,#,!text/keyspec_right_parenthesis,!text/keyspec_left_parenthesis,/,;,',@,:,-,\",+,\\%,&",
         // U+2020: "†" DAGGER
         // U+2021: "‡" DOUBLE DAGGER
@@ -325,9 +326,8 @@
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "\u00BF",
         /* morekeys_h ~ */
-        EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
-        EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
-        /* ~ morekeys_swiss_row2_11 */
+        EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
+        /* ~ keyspec_south_slavic_row3_8 */
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         /* keyspec_spanish_row2_10 */ "\u00F1",
         // U+266A: "♪" EIGHTH NOTE
@@ -571,7 +571,9 @@
         // U+066B: "٫" ARABIC DECIMAL SEPARATOR
         // U+066C: "٬" ARABIC THOUSANDS SEPARATOR
         /* additional_morekeys_symbols_0 */ "0,\u066B,\u066C",
-        /* morekeys_punctuation */ null,
+        /* keyspec_swiss_row1_11 ~ */
+        null, null, null, null, null, null, null,
+        /* ~ morekeys_punctuation */
         // U+2605: "★" BLACK STAR
         // U+066D: "٭" ARABIC FIVE POINTED STAR
         /* morekeys_star */ "\u2605,\u066D",
@@ -603,8 +605,7 @@
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "?,\u00BF",
         /* morekeys_h ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ keyspec_spanish_row2_10 */
         // U+266A: "♪" EIGHTH NOTE
         /* morekeys_bullet */ "\u266A",
@@ -806,15 +807,14 @@
         /* morekeys_g ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null,
-        /* ~ additional_morekeys_symbols_0 */
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ morekeys_swiss_row2_11 */
         // U+00B7: "·" MIDDLE DOT
         /* morekeys_punctuation */ "!autoColumnOrder!9,\\,,?,!,\u00B7,#,),(,/,;,',@,:,-,\",+,\\%,&",
         /* morekeys_star ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null,
-        /* ~ morekeys_swiss_row2_11 */
+        /* ~ keyspec_south_slavic_row3_8 */
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* keyspec_spanish_row2_10 */ "\u00E7",
         /* morekeys_bullet ~ */
@@ -981,7 +981,7 @@
         // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-        /* morekeys_a */ "\u00E4,\u00E2,\u00E0,\u00E1,\u00E6,\u00E3,\u00E5,\u0101",
+        /* morekeys_a */ "\u00E4,%,\u00E2,\u00E0,\u00E1,\u00E6,\u00E3,\u00E5,\u0101",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
         // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
@@ -990,13 +990,13 @@
         // U+0153: "œ" LATIN SMALL LIGATURE OE
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-        /* morekeys_o */ "\u00F6,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u00F8,\u014D",
+        /* morekeys_o */ "\u00F6,%,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u00F8,\u014D",
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+        /* morekeys_u */ "\u00FC,%,\u00FB,\u00F9,\u00FA,\u016B",
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -1023,10 +1023,8 @@
         /* keyspec_currency ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null,
-        /* ~ keyspec_south_slavic_row3_8 */
+        null, null, null, null, null,
+        /* ~ additional_morekeys_symbols_0 */
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* keyspec_swiss_row1_11 */ "\u00FC",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
@@ -1220,7 +1218,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_question */
         // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
         // U+0127: "ħ" LATIN SMALL LETTER H WITH STROKE
@@ -1228,9 +1226,8 @@
         // U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX
         /* morekeys_w */ "w,\u0175",
         /* morekeys_east_slavic_row2_2 ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null,
-        /* ~ morekeys_swiss_row2_11 */
+        null, null, null, null, null, null, null, null, null, null,
+        /* ~ keyspec_south_slavic_row3_8 */
         // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
         /* keyspec_spanish_row2_10 */ "\u0135",
         /* morekeys_bullet ~ */
@@ -1307,8 +1304,8 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null,
-        /* ~ additional_morekeys_symbols_0 */
+        null, null, null, null, null, null, null,
+        /* ~ morekeys_swiss_row2_11 */
         // U+00A1: "¡" INVERTED EXCLAMATION MARK
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_punctuation */ "!autoColumnOrder!9,\\,,?,!,#,),(,/,;,\u00A1,',@,:,-,\",+,\\%,&,\u00BF",
@@ -1525,7 +1522,9 @@
         // U+066B: "٫" ARABIC DECIMAL SEPARATOR
         // U+066C: "٬" ARABIC THOUSANDS SEPARATOR
         /* additional_morekeys_symbols_0 */ "0,\u066B,\u066C",
-        /* morekeys_punctuation */ null,
+        /* keyspec_swiss_row1_11 ~ */
+        null, null, null, null, null, null, null,
+        /* ~ morekeys_punctuation */
         // U+2605: "★" BLACK STAR
         // U+066D: "٭" ARABIC FIVE POINTED STAR
         /* morekeys_star */ "\u2605,\u066D",
@@ -1553,8 +1552,7 @@
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "?,\u00BF",
         /* morekeys_h ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ keyspec_spanish_row2_10 */
         // U+266A: "♪" EIGHTH NOTE
         /* morekeys_bullet */ "\u266A",
@@ -1714,10 +1712,8 @@
         /* morekeys_d ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keyspec_south_slavic_row3_8 */
+        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ additional_morekeys_symbols_0 */
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         /* keyspec_swiss_row1_11 */ "\u00E8",
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
@@ -1938,8 +1934,9 @@
         /* morekeys_s ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ additional_morekeys_symbols_0 */
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null,
+        /* ~ morekeys_swiss_row2_11 */
         // U+055E: "՞" ARMENIAN QUESTION MARK
         // U+055C: "՜" ARMENIAN EXCLAMATION MARK
         // U+055A: "՚" ARMENIAN APOSTROPHE
@@ -1967,8 +1964,7 @@
         /* morekeys_h ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_greater_than */
         // U+0589: "։" ARMENIAN FULL STOP
         /* keyspec_period */ "\u0589",
@@ -2078,6 +2074,24 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00EC,\u00ED,\u00EE,\u00EF,\u012F,\u012B",
+        /* morekeys_c ~ */
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null,
+        /* ~ additional_morekeys_symbols_0 */
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        /* keyspec_swiss_row1_11 */ "\u00FC",
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+        /* keyspec_swiss_row2_10 */ "\u00F6",
+        // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        /* keyspec_swiss_row2_11 */ "\u00E4",
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        /* morekeys_swiss_row1_11 */ "\u00E8",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        /* morekeys_swiss_row2_10 */ "\u00E9",
+        // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+        /* morekeys_swiss_row2_11 */ "\u00E0",
     };
 
     /* Locale iw: Hebrew */
@@ -2101,7 +2115,7 @@
         /* morekeys_r ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_punctuation */
         // U+2605: "★" BLACK STAR
         /* morekeys_star */ "\u2605",
@@ -2130,8 +2144,7 @@
         /* keyspec_tablet_comma ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_tablet_punctuation */
         // U+00B1: "±" PLUS-MINUS SIGN
         // U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
@@ -2184,7 +2197,8 @@
         /* morekeys_nordic_row2_11 ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null,
         /* ~ morekeys_w */
         // U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
         /* morekeys_east_slavic_row2_2 */ "\u0456",
@@ -2199,8 +2213,7 @@
         /* morekeys_cyrillic_o */ "\u04E9",
         /* morekeys_cyrillic_i ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ keyspec_x */
         // U+04BB: "һ" CYRILLIC SMALL LETTER SHHA
         /* morekeys_east_slavic_row2_11 */ "\u04BB",
@@ -2265,7 +2278,8 @@
         /* morekeys_nordic_row2_11 ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null,
         /* ~ morekeys_east_slavic_row2_2 */
         // U+04AF: "ү" CYRILLIC SMALL LETTER STRAIGHT U
         /* morekeys_cyrillic_u */ "\u04AF",
@@ -2504,7 +2518,8 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_cyrillic_o */
         // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
         /* morekeys_cyrillic_i */ "\u045D",
@@ -3045,7 +3060,8 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_cyrillic_o */
         // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
         /* morekeys_cyrillic_i */ "\u045D",
@@ -3369,7 +3385,8 @@
         /* morekeys_nordic_row2_11 ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null,
         /* ~ morekeys_w */
         // U+0457: "ї" CYRILLIC SMALL LETTER YI
         /* morekeys_east_slavic_row2_2 */ "\u0457",
@@ -3639,7 +3656,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_question */
         // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
         /* morekeys_h */ "\u0125",
@@ -3647,8 +3664,7 @@
         /* morekeys_w */ "\u0175",
         /* morekeys_east_slavic_row2_2 ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_v */
         // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
         /* morekeys_j */ "\u0135",
@@ -3665,32 +3681,32 @@
         "ca"     , TEXTS_ca,    /*  11/120 Catalan */
         "cs"     , TEXTS_cs,    /*  17/ 21 Czech */
         "da"     , TEXTS_da,    /*  19/ 33 Danish */
-        "de"     , TEXTS_de,    /*  16/ 91 German */
+        "de"     , TEXTS_de,    /*  16/ 60 German */
         "el"     , TEXTS_el,    /*   1/ 10 Greek */
         "en"     , TEXTS_en,    /*   8/ 11 English */
         "eo"     , TEXTS_eo,    /*  26/115 Esperanto */
-        "es"     , TEXTS_es,    /*   8/ 55 Spanish */
+        "es"     , TEXTS_es,    /*   8/ 61 Spanish */
         "et_EE"  , TEXTS_et_EE, /*  22/ 27 Estonian (Estonia) */
         "eu_ES"  , TEXTS_eu_ES, /*   7/  8 Basque (Spain) */
         "fa"     , TEXTS_fa,    /*  58/123 Persian */
         "fi"     , TEXTS_fi,    /*  10/ 33 Finnish */
-        "fr"     , TEXTS_fr,    /*  13/ 91 French */
+        "fr"     , TEXTS_fr,    /*  13/ 60 French */
         "gl_ES"  , TEXTS_gl_ES, /*   7/  8 Gallegan (Spain) */
         "hi"     , TEXTS_hi,    /*  23/ 54 Hindi */
         "hr"     , TEXTS_hr,    /*   9/ 19 Croatian */
         "hu"     , TEXTS_hu,    /*   9/ 19 Hungarian */
         "hy_AM"  , TEXTS_hy_AM, /*   8/126 Armenian (Armenia) */
         "is"     , TEXTS_is,    /*  10/ 15 Icelandic */
-        "it"     , TEXTS_it,    /*   5/  5 Italian */
+        "it"     , TEXTS_it,    /*  11/ 60 Italian */
         "iw"     , TEXTS_iw,    /*  20/121 Hebrew */
         "ka_GE"  , TEXTS_ka_GE, /*   3/ 10 Georgian (Georgia) */
         "kk"     , TEXTS_kk,    /*  15/118 Kazakh */
         "km_KH"  , TEXTS_km_KH, /*   2/119 Khmer (Cambodia) */
-        "ky"     , TEXTS_ky,    /*  10/ 80 Kirghiz */
+        "ky"     , TEXTS_ky,    /*  10/ 86 Kirghiz */
         "lo_LA"  , TEXTS_lo_LA, /*   2/ 20 Lao (Laos) */
         "lt"     , TEXTS_lt,    /*  18/ 22 Lithuanian */
         "lv"     , TEXTS_lv,    /*  18/ 22 Latvian */
-        "mk"     , TEXTS_mk,    /*   9/ 85 Macedonian */
+        "mk"     , TEXTS_mk,    /*   9/ 91 Macedonian */
         "mn_MN"  , TEXTS_mn_MN, /*   2/ 20 Mongolian (Mongolia) */
         "my_MM"  , TEXTS_my_MM, /*   1/ 10 Burmese (Myanmar) */
         "nb"     , TEXTS_nb,    /*  11/ 33 Norwegian Bokmål */
@@ -3703,13 +3719,13 @@
         "ru"     , TEXTS_ru,    /*   9/ 32 Russian */
         "sk"     , TEXTS_sk,    /*  20/ 22 Slovak */
         "sl"     , TEXTS_sl,    /*   8/ 19 Slovenian */
-        "sr"     , TEXTS_sr,    /*  11/ 85 Serbian */
+        "sr"     , TEXTS_sr,    /*  11/ 91 Serbian */
         "sv"     , TEXTS_sv,    /*  21/ 33 Swedish */
         "sw"     , TEXTS_sw,    /*   9/ 17 Swahili */
         "th"     , TEXTS_th,    /*   2/ 20 Thai */
         "tl"     , TEXTS_tl,    /*   7/  8 Tagalog */
         "tr"     , TEXTS_tr,    /*   7/ 17 Turkish */
-        "uk"     , TEXTS_uk,    /*  11/ 79 Ukrainian */
+        "uk"     , TEXTS_uk,    /*  11/ 85 Ukrainian */
         "vi"     , TEXTS_vi,    /*   8/ 20 Vietnamese */
         "zu"     , TEXTS_zu,    /*   8/ 11 Zulu */
         "zz"     , TEXTS_zz,    /*  19/109 Alphabet */
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 6d36af7..0594c68 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -199,7 +199,8 @@
                         latinIme.mSettings.getCurrent());
                 break;
             case MSG_UPDATE_SHIFT_STATE:
-                switcher.requestUpdatingShiftState();
+                switcher.requestUpdatingShiftState(latinIme.getCurrentAutoCapsState(),
+                        latinIme.getCurrentRecapitalizeState());
                 break;
             case MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP:
                 if (msg.arg1 == ARG1_NOT_GESTURE_INPUT) {
@@ -635,6 +636,11 @@
         super.onDestroy();
     }
 
+    @UsedForTesting
+    public void recycle() {
+        mInputLogic.recycle();
+    }
+
     @Override
     public void onConfigurationChanged(final Configuration conf) {
         // If orientation changed while predicting, commit the change
@@ -838,7 +844,8 @@
             // we need to re-evaluate the shift state, but not the whole layout which would be
             // disruptive.
             // Space state must be updated before calling updateShiftState
-            switcher.requestUpdatingShiftState();
+            switcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
+                    getCurrentRecapitalizeState());
         }
         // This will set the punctuation suggestions if next word suggestion is off;
         // otherwise it will clear the suggestion strip.
@@ -917,7 +924,8 @@
         // TODO: find a better way to simulate actual execution.
         if (isInputViewShown() &&
                 mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd)) {
-            mKeyboardSwitcher.requestUpdatingShiftState();
+            mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
+                    getCurrentRecapitalizeState());
         }
 
         mSubtypeState.currentSubtypeUsed();
@@ -1261,7 +1269,8 @@
         // TODO: have the keyboard pass the correct key code when we need it.
         final Event event = Event.createSoftwareTextEvent(rawText, Event.NOT_A_KEY_CODE);
         mInputLogic.onTextInput(mSettings.getCurrent(), event, mHandler);
-        mKeyboardSwitcher.requestUpdatingShiftState();
+        mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
+                getCurrentRecapitalizeState());
         mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT, getCurrentAutoCapsState());
     }
 
@@ -1505,7 +1514,8 @@
             mHandler.postUpdateShiftState();
             break;
         case InputTransaction.SHIFT_UPDATE_NOW:
-            mKeyboardSwitcher.requestUpdatingShiftState();
+            mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
+                    getCurrentRecapitalizeState());
             break;
         default: // SHIFT_NO_UPDATE
         }
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 7cf8c5e..bf8467e 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -148,6 +148,17 @@
         mInputLogicHandler.reset();
     }
 
+    // Normally this class just gets out of scope after the process ends, but in unit tests, we
+    // create several instances of LatinIME in the same process, which results in several
+    // instances of InputLogic. This cleans up the associated handler so that tests don't leak
+    // handlers.
+    public void recycle() {
+        final InputLogicHandler inputLogicHandler = mInputLogicHandler;
+        mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
+        inputLogicHandler.destroy();
+        mSuggest.mDictionaryFacilitator.closeDictionaries();
+    }
+
     /**
      * React to a string input.
      *
@@ -537,7 +548,8 @@
                 // after typing some letters and a period, then gesturing; the keyboard is not in
                 // caps mode yet, but since a gesture is starting, it should go in caps mode,
                 // unless the user explictly said it should not.
-                keyboardSwitcher.requestUpdatingShiftState();
+                keyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(settingsValues),
+                        getCurrentRecapitalizeState());
             }
         }
         mConnection.endBatchEdit();
@@ -579,7 +591,8 @@
                     promotePhantomSpace(settingsValues);
                     mConnection.commitText(commitParts[0], 0);
                     mSpaceState = SpaceState.PHANTOM;
-                    keyboardSwitcher.requestUpdatingShiftState();
+                    keyboardSwitcher.requestUpdatingShiftState(
+                            getCurrentAutoCapsState(settingsValues), getCurrentRecapitalizeState());
                     mWordComposer.setCapitalizedModeAndPreviousWordAtStartComposingTime(
                             getActualCapsMode(settingsValues,
                                     keyboardSwitcher.getKeyboardShiftMode()), commitParts[0]);
@@ -1819,7 +1832,8 @@
         }
         // Space state must be updated before calling updateShiftState
         mSpaceState = SpaceState.PHANTOM;
-        keyboardSwitcher.requestUpdatingShiftState();
+        keyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(settingsValues),
+                getCurrentRecapitalizeState());
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index e3b8ab4..64bba68 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -20,6 +20,7 @@
 import android.os.HandlerThread;
 import android.os.Message;
 
+import com.android.inputmethod.compat.LooperCompatUtils;
 import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.LatinIME;
 import com.android.inputmethod.latin.Suggest;
@@ -80,6 +81,12 @@
         mNonUIThreadHandler.removeCallbacksAndMessages(null);
     }
 
+    // In unit tests, we create several instances of LatinIME, which results in several instances
+    // of InputLogicHandler. To avoid these handlers lingering, we call this.
+    public void destroy() {
+        LooperCompatUtils.quitSafely(mNonUIThreadHandler.getLooper());
+    }
+
     /**
      * Handle a message.
      * @see android.os.Handler.Callback#handleMessage(android.os.Message)
diff --git a/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java b/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java
index 89837c6..1ca895f 100644
--- a/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java
@@ -18,8 +18,6 @@
 
 import android.view.inputmethod.InputMethodSubtype;
 
-import java.util.Locale;
-
 public final class SpacebarLanguageUtils {
     private SpacebarLanguageUtils() {
         // Intentional empty constructor for utility class.
@@ -55,7 +53,6 @@
         if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
             return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype);
         }
-        final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
-        return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage());
+        return SubtypeLocaleUtils.getSubtypeLanguageDisplayName(subtype.getLocale());
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 2452864..b37779b 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -25,7 +25,7 @@
 import android.util.Log;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.latin.DictionaryFactory;
+import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
 
 import java.util.Arrays;
@@ -33,10 +33,10 @@
 import java.util.Locale;
 
 public final class SubtypeLocaleUtils {
-    static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
-    // This class must be located in the same package as LatinIME.java.
-    private static final String RESOURCE_PACKAGE_NAME =
-            DictionaryFactory.class.getPackage().getName();
+    private static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
+
+    // This reference class {@link Constants} must be located in the same package as LatinIME.java.
+    private static final String RESOURCE_PACKAGE_NAME = Constants.class.getPackage().getName();
 
     // Special language code to represent "no language".
     public static final String NO_LANGUAGE = "zz";
@@ -44,7 +44,8 @@
     public static final String EMOJI = "emoji";
     public static final int UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic;
 
-    private static boolean sInitialized = false;
+    private static volatile boolean sInitialized = false;
+    private static final Object sInitializeLock = new Object();
     private static Resources sResources;
     private static String[] sPredefinedKeyboardLayoutSet;
     // Keyboard layout to its display name map.
@@ -77,9 +78,16 @@
     }
 
     // Note that this initialization method can be called multiple times.
-    public static synchronized void init(final Context context) {
-        if (sInitialized) return;
+    public static void init(final Context context) {
+        synchronized (sInitializeLock) {
+            if (sInitialized == false) {
+                initLocked(context);
+                sInitialized = true;
+            }
+        }
+    }
 
+    private static void initLocked(final Context context) {
         final Resources res = context.getResources();
         sResources = res;
 
@@ -122,8 +130,6 @@
             final String keyboardLayoutSet = keyboardLayoutSetMap[i + 1];
             sLocaleAndExtraValueToKeyboardLayoutSetMap.put(key, keyboardLayoutSet);
         }
-
-        sInitialized = true;
     }
 
     public static String[] getPredefinedKeyboardLayoutSet() {
@@ -167,8 +173,18 @@
         return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
     }
 
+    public static String getSubtypeLanguageDisplayName(final String localeString) {
+        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
+        final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
+        return getSubtypeLocaleDisplayNameInternal(locale.getLanguage(), displayLocale);
+    }
+
     private static String getSubtypeLocaleDisplayNameInternal(final String localeString,
             final Locale displayLocale) {
+        if (NO_LANGUAGE.equals(localeString)) {
+            // No language subtype should be displayed in system locale.
+            return sResources.getString(R.string.subtype_no_language);
+        }
         final Integer exceptionalNameResId = sExceptionalLocaleToNameIdsMap.get(localeString);
         final String displayName;
         if (exceptionalNameResId != null) {
@@ -179,9 +195,6 @@
                 }
             };
             displayName = getExceptionalName.runInLocale(sResources, displayLocale);
-        } else if (NO_LANGUAGE.equals(localeString)) {
-            // No language subtype should be displayed in system locale.
-            return sResources.getString(R.string.subtype_no_language);
         } else {
             final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
             displayName = locale.getDisplayName(displayLocale);
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
index 18390b2..e4aaf03 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
@@ -25,8 +25,8 @@
 
 @SmallTest
 public class KeyboardLayoutSetSubtypesCountTests extends KeyboardLayoutSetTestsBase {
-    private static final int NUMBER_OF_SUBTYPES = 69;
-    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 44;
+    private static final int NUMBER_OF_SUBTYPES = 70;
+    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 45;
     private static final int NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES = 2;
 
     private static String toString(final ArrayList<InputMethodSubtype> subtypeList) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Greek.java b/tests/src/com/android/inputmethod/keyboard/layout/Greek.java
index 0ec9f4c..475052c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Greek.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Greek.java
@@ -85,7 +85,7 @@
                     key(ROW1_2, moreKey("2")),
                     // U+03B5: "ε" GREEK SMALL LETTER EPSILON
                     // U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS
-                    key("\u03B5", joinMoreKeys("3", "\u03AD")),
+                    key("\u03B5", joinMoreKeys("\u03AD", "3")),
                     // U+03C1: "ρ" GREEK SMALL LETTER RHO
                     key("\u03C1", moreKey("4")),
                     // U+03C4: "τ" GREEK SMALL LETTER TAU
@@ -94,17 +94,17 @@
                     // U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
                     // U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
                     // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
-                    key("\u03C5", joinMoreKeys("6", "\u03CD", "\u03CB", "\u03B0")),
+                    key("\u03C5", joinMoreKeys("\u03CD", "6", "\u03CB", "\u03B0")),
                     // U+03B8: "θ" GREEK SMALL LETTER THETA
                     key("\u03B8", moreKey("7")),
                     // U+03B9: "ι" GREEK SMALL LETTER IOTA
                     // U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
                     // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
                     // U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
-                    key("\u03B9", joinMoreKeys("8", "\u03AF", "\u03CA", "\u0390")),
+                    key("\u03B9", joinMoreKeys("\u03AF", "8", "\u03CA", "\u0390")),
                     // U+03BF: "ο" GREEK SMALL LETTER OMICRON
                     // U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS
-                    key("\u03BF", joinMoreKeys("9", "\u03CC")),
+                    key("\u03BF", joinMoreKeys("\u03CC", "9")),
                     // U+03C0: "π" GREEK SMALL LETTER PI
                     key("\u03C0", moreKey("0")))
             .setKeysOfRow(2,
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/GermanCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/GermanCustomizer.java
index cd88140..6d38937 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/GermanCustomizer.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/GermanCustomizer.java
@@ -53,6 +53,7 @@
                 // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
                 // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
                 .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B")
+                .setAdditionalMoreKeysPositionOf("u", 2)
                 // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
                 // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
                 // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
@@ -64,6 +65,7 @@
                 .setMoreKeysOf("o",
                         "\u00F6", "\u00F4", "\u00F2", "\u00F3", "\u00F5", "\u0153", "\u00F8",
                         "\u014D")
+                .setAdditionalMoreKeysPositionOf("o", 2)
                 // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
                 // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
                 // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
@@ -75,6 +77,7 @@
                 .setMoreKeysOf("a",
                         "\u00E4", "\u00E2", "\u00E0", "\u00E1", "\u00E6", "\u00E3", "\u00E5",
                         "\u0101")
+                .setAdditionalMoreKeysPositionOf("a", 2)
                 // U+00DF: "ß" LATIN SMALL LETTER SHARP S
                 // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
                 // U+0161: "š" LATIN SMALL LETTER S WITH CARON
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/ItalianCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/ItalianCustomizer.java
new file mode 100644
index 0000000..7350709
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/ItalianCustomizer.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+class ItalianCustomizer extends LayoutCustomizer {
+    public ItalianCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setMoreKeysOf("e",
+                        "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00F9", "\u00FA", "\u00FB", "\u00FC", "\u016B")
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                .setMoreKeysOf("i", "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u012F", "\u012B")
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+                .setMoreKeysOf("o",
+                        "\u00F2", "\u00F3", "\u00F4", "\u00F6", "\u00F5", "\u0153", "\u00F8",
+                        "\u014D", "\u00BA")
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+                .setMoreKeysOf("a",
+                        "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5",
+                        "\u0101", "\u00AA");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java
index 4a22003..f3c610c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java
@@ -31,63 +31,22 @@
 @SmallTest
 public final class TestsItalian extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("it");
-    private static final LayoutBase LAYOUT = new Qwerty(new ItalianCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Qwerty(new ItalianITCustomizer(LOCALE));
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
 
-    private static class ItalianCustomizer extends EuroCustomizer {
-        public ItalianCustomizer(final Locale locale) { super(locale); }
+    private static class ItalianITCustomizer extends EuroCustomizer {
+        private final ItalianCustomizer mItalianCustomizer;
+
+        public ItalianITCustomizer(final Locale locale) {
+            super(locale);
+            mItalianCustomizer = new ItalianCustomizer(locale);
+        }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                    // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                    // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                    // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                    // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                    // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                    // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                    .setMoreKeysOf("e",
-                            "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    .setMoreKeysOf("u", "\u00F9", "\u00FA", "\u00FB", "\u00FC", "\u016B")
-                    // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                    // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                    // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                    // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                    .setMoreKeysOf("i", "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u012F", "\u012B")
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    // U+00BA: "º" MASCULINE ORDINAL INDICATOR
-                    .setMoreKeysOf("o",
-                            "\u00F2", "\u00F3", "\u00F4", "\u00F6", "\u00F5", "\u0153", "\u00F8",
-                            "\u014D", "\u00BA")
-                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                    // U+00AA: "ª" FEMININE ORDINAL INDICATOR
-                    .setMoreKeysOf("a",
-                            "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5",
-                            "\u0101", "\u00AA");
+            return mItalianCustomizer.setAccentedLetters(builder);
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalianCH.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalianCH.java
new file mode 100644
index 0000000..d32f9e9
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalianCH.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Swiss;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * it_CH: Italian (Switzerland)/swiss
+ */
+@SmallTest
+public final class TestsItalianCH extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("it", "CH");
+    private static final LayoutBase LAYOUT = new Swiss(new ItalianCHCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class ItalianCHCustomizer extends ItalianCustomizer {
+        public ItalianCHCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+            super.setAccentedLetters(builder);
+            return builder
+                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                    // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                    .replaceKeyOfLabel(Swiss.ROW1_11, key("\u00FC", moreKey("\u00E8")))
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                    .replaceKeyOfLabel(Swiss.ROW2_10, key("\u00F6", moreKey("\u00E9")))
+                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                    .replaceKeyOfLabel(Swiss.ROW2_11, key("\u00E4", moreKey("\u00E0")));
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 1383ff9..e5f111a 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -213,13 +213,18 @@
 
     @Override
     protected void tearDown() throws Exception {
+        mLatinIME.onFinishInputView(true);
+        mLatinIME.onFinishInput();
+        runMessages();
         mLatinIME.mHandler.removeAllMessages();
         setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, mPreviousBigramPredictionSettings,
                 true /* defaultValue */);
         setStringPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD, mPreviousAutoCorrectSetting,
                 DEFAULT_AUTO_CORRECTION_THRESHOLD);
         setDebugMode(false);
+        mLatinIME.recycle();
         super.tearDown();
+        mLatinIME = null;
     }
 
     // We need to run the messages added to the handler from LatinIME. The only way to do
diff --git a/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml
index 94b1724..0c6d3ad 100644
--- a/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml
@@ -26,7 +26,7 @@
          U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
          U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
-    <string name="morekeys_a">&#x00E4;,&#x00E2;,&#x00E0;,&#x00E1;,&#x00E6;,&#x00E3;,&#x00E5;,&#x0101;</string>
+    <string name="morekeys_a">&#x00E4;,%,&#x00E2;,&#x00E0;,&#x00E1;,&#x00E6;,&#x00E3;,&#x00E5;,&#x0101;</string>
     <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
          U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
          U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -41,13 +41,13 @@
          U+0153: "œ" LATIN SMALL LIGATURE OE
          U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
          U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
-    <string name="morekeys_o">&#x00F6;,&#x00F4;,&#x00F2;,&#x00F3;,&#x00F5;,&#x0153;,&#x00F8;,&#x014D;</string>
+    <string name="morekeys_o">&#x00F6;,%,&#x00F4;,&#x00F2;,&#x00F3;,&#x00F5;,&#x0153;,&#x00F8;,&#x014D;</string>
     <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
          U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
          U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
          U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
          U+016B: "ū" LATIN SMALL LETTER U WITH MACRON -->
-    <string name="morekeys_u">&#x00FC;,&#x00FB;,&#x00F9;,&#x00FA;,&#x016B;</string>
+    <string name="morekeys_u">&#x00FC;,%,&#x00FB;,&#x00F9;,&#x00FA;,&#x016B;</string>
     <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S
          U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
          U+0161: "š" LATIN SMALL LETTER S WITH CARON -->
diff --git a/tools/make-keyboard-text/res/values-it/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-it/donottranslate-more-keys.xml
index 6492553..e809f48 100644
--- a/tools/make-keyboard-text/res/values-it/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-it/donottranslate-more-keys.xml
@@ -59,4 +59,16 @@
          U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
          U+016B: "ū" LATIN SMALL LETTER U WITH MACRON -->
     <string name="morekeys_u">&#x00F9;,&#x00FA;,&#x00FB;,&#x00FC;,&#x016B;</string>
+    <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS -->
+    <string name="keyspec_swiss_row1_11">&#x00FC;</string>
+    <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE -->
+    <string name="morekeys_swiss_row1_11">&#x00E8;</string>
+    <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS -->
+    <string name="keyspec_swiss_row2_10">&#x00F6;</string>
+    <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE -->
+    <string name="morekeys_swiss_row2_10">&#x00E9;</string>
+    <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS -->
+    <string name="keyspec_swiss_row2_11">&#x00E4;</string>
+    <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE -->
+    <string name="morekeys_swiss_row2_11">&#x00E0;</string>
 </resources>