Merge "Don't reset the value needed before it's used"
diff --git a/java/res/xml-sw600dp/key_greek_semicolon.xml b/java/res/xml-sw600dp/key_greek_semicolon.xml
deleted file mode 100644
index 9e2c1fa..0000000
--- a/java/res/xml-sw600dp/key_greek_semicolon.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <Key
-        latin:keySpec=";"
-        latin:keyHintLabel=":"
-        latin:moreKeys=":"
-        latin:keyStyle="hasShiftedLetterHintStyle" />
-</merge>
diff --git a/java/res/xml-sw600dp/rows_greek.xml b/java/res/xml-sw600dp/rows_greek.xml
index 066dc47..60ee478 100644
--- a/java/res/xml-sw600dp/rows_greek.xml
+++ b/java/res/xml-sw600dp/rows_greek.xml
@@ -27,8 +27,6 @@
         latin:keyWidth="9.0%p"
     >
         <include
-            latin:keyboardLayout="@xml/key_greek_semicolon" />
-        <include
             latin:keyboardLayout="@xml/rowkeys_greek1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
diff --git a/java/res/xml/key_greek_semicolon.xml b/java/res/xml/key_greek_semicolon.xml
deleted file mode 100644
index 9001e4d..0000000
--- a/java/res/xml/key_greek_semicolon.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <switch>
-        <case
-            latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
-        >
-            <Key
-                latin:keySpec=":"
-                latin:keyHintLabel="1"
-                latin:moreKeys=";"
-                latin:additionalMoreKeys="1" />
-        </case>
-        <default>
-            <Key
-                latin:keySpec=";"
-                latin:keyHintLabel="1"
-                latin:moreKeys=":"
-                latin:additionalMoreKeys="1" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_greek1.xml b/java/res/xml/rowkeys_greek1.xml
index 5080dc8..c5033d0 100644
--- a/java/res/xml/rowkeys_greek1.xml
+++ b/java/res/xml/rowkeys_greek1.xml
@@ -21,6 +21,24 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
+    <switch>
+        <case
+            latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+        >
+            <Key
+                latin:keySpec=":"
+                latin:keyHintLabel="1"
+                latin:moreKeys=";"
+                latin:additionalMoreKeys="1" />
+        </case>
+        <default>
+            <Key
+                latin:keySpec=";"
+                latin:keyHintLabel="1"
+                latin:moreKeys=":"
+                latin:additionalMoreKeys="1" />
+        </default>
+    </switch>
     <!-- TODO: Should find a way to compound Greek dialytika tonos and other Greek letters. -->
     <!--
     <switch>
diff --git a/java/res/xml/rows_greek.xml b/java/res/xml/rows_greek.xml
index ca6d240..e00b927 100644
--- a/java/res/xml/rows_greek.xml
+++ b/java/res/xml/rows_greek.xml
@@ -27,8 +27,6 @@
         latin:keyWidth="10%p"
     >
         <include
-            latin:keyboardLayout="@xml/key_greek_semicolon" />
-        <include
             latin:keyboardLayout="@xml/rowkeys_greek1" />
     </Row>
     <Row
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index a8d6e49..387ed39 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -101,10 +101,10 @@
         /*  19: 9 */ "keylabel_for_currency",
         /*  20: 8 */ "more_keys_for_r",
         /*  21: 6 */ "more_keys_for_k",
-        /*  22: 6 */ "keylabel_for_nordic_row1_11",
-        /*  23: 6 */ "keylabel_for_nordic_row2_10",
-        /*  24: 6 */ "keylabel_for_nordic_row2_11",
-        /*  25: 6 */ "more_keys_for_cyrillic_ie",
+        /*  22: 6 */ "more_keys_for_cyrillic_ie",
+        /*  23: 5 */ "keylabel_for_nordic_row1_11",
+        /*  24: 5 */ "keylabel_for_nordic_row2_10",
+        /*  25: 5 */ "keylabel_for_nordic_row2_11",
         /*  26: 5 */ "more_keys_for_nordic_row2_10",
         /*  27: 5 */ "keylabel_for_east_slavic_row1_9",
         /*  28: 5 */ "keylabel_for_east_slavic_row2_2",
@@ -714,11 +714,13 @@
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* label_to_alpha_key */ "\u0410\u0411\u0412",
         /* more_keys_for_y ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keylabel_for_nordic_row2_11 */
+        null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ more_keys_for_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* more_keys_for_cyrillic_ie */ "\u0451",
-        /* more_keys_for_nordic_row2_10 */ null,
+        /* keylabel_for_nordic_row1_11 ~ */
+        null, null, null, null,
+        /* ~ more_keys_for_nordic_row2_10 */
         // U+045E: "ў" CYRILLIC SMALL LETTER SHORT U
         /* keylabel_for_east_slavic_row1_9 */ "\u045E",
         // U+044B: "ы" CYRILLIC SMALL LETTER YERU
@@ -959,15 +961,14 @@
         /* single_angle_quotes */ "!text/single_raqm_laqm",
         /* double_angle_quotes */ "!text/double_raqm_laqm",
         /* keylabel_for_currency ~ */
-        null, null, null,
-        /* ~ more_keys_for_k */
+        null, null, null, null,
+        /* ~ more_keys_for_cyrillic_ie */
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         /* keylabel_for_nordic_row1_11 */ "\u00E5",
         // U+00E6: "æ" LATIN SMALL LETTER AE
         /* keylabel_for_nordic_row2_10 */ "\u00E6",
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         /* keylabel_for_nordic_row2_11 */ "\u00F8",
-        /* more_keys_for_cyrillic_ie */ null,
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         /* more_keys_for_nordic_row2_10 */ "\u00E4",
         /* keylabel_for_east_slavic_row1_9 ~ */
@@ -1220,7 +1221,7 @@
         // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
         // U+0138: "ĸ" LATIN SMALL LETTER KRA
         /* more_keys_for_k */ "\u0137,\u0138",
-        /* keylabel_for_nordic_row1_11 ~ */
+        /* more_keys_for_cyrillic_ie ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -1413,13 +1414,13 @@
         /* more_keys_for_r */ "\u0157,\u0159,\u0155",
         // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
         /* more_keys_for_k */ "\u0137",
+        /* more_keys_for_cyrillic_ie */ null,
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* keylabel_for_nordic_row1_11 */ "\u00FC",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         /* keylabel_for_nordic_row2_10 */ "\u00F6",
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         /* keylabel_for_nordic_row2_11 */ "\u00E4",
-        /* more_keys_for_cyrillic_ie */ null,
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         /* more_keys_for_nordic_row2_10 */ "\u00F5",
     };
@@ -1604,15 +1605,14 @@
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         /* more_keys_for_z */ "\u017E,\u017A,\u017C",
         /* more_keys_for_t ~ */
-        null, null, null, null, null, null, null, null,
-        /* ~ more_keys_for_k */
+        null, null, null, null, null, null, null, null, null,
+        /* ~ more_keys_for_cyrillic_ie */
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         /* keylabel_for_nordic_row1_11 */ "\u00E5",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         /* keylabel_for_nordic_row2_10 */ "\u00F6",
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         /* keylabel_for_nordic_row2_11 */ "\u00E4",
-        /* more_keys_for_cyrillic_ie */ null,
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         /* more_keys_for_nordic_row2_10 */ "\u00F8",
         /* keylabel_for_east_slavic_row1_9 ~ */
@@ -1942,15 +1942,6 @@
         /* more_keys_for_z */ null,
         // U+00FE: "þ" LATIN SMALL LETTER THORN
         /* more_keys_for_t */ "\u00FE",
-        /* more_keys_for_l ~ */
-        null, null, null, null, null, null, null,
-        /* ~ more_keys_for_k */
-        // U+00F0: "ð" LATIN SMALL LETTER ETH
-        /* keylabel_for_nordic_row1_11 */ "\u00F0",
-        // U+00E6: "æ" LATIN SMALL LETTER AE
-        /* keylabel_for_nordic_row2_10 */ "\u00E6",
-        // U+00FE: "þ" LATIN SMALL LETTER THORN
-        /* keylabel_for_nordic_row2_11 */ "\u00FE",
     };
 
     /* Language it: Italian */
@@ -2085,11 +2076,13 @@
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* label_to_alpha_key */ "\u0410\u0411\u0412",
         /* more_keys_for_y ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keylabel_for_nordic_row2_11 */
+        null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ more_keys_for_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* more_keys_for_cyrillic_ie */ "\u0451",
-        /* more_keys_for_nordic_row2_10 */ null,
+        /* keylabel_for_nordic_row1_11 ~ */
+        null, null, null, null,
+        /* ~ more_keys_for_nordic_row2_10 */
         // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA
         /* keylabel_for_east_slavic_row1_9 */ "\u0449",
         // U+044B: "ы" CYRILLIC SMALL LETTER YERU
@@ -2162,11 +2155,13 @@
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* label_to_alpha_key */ "\u0410\u0411\u0412",
         /* more_keys_for_y ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keylabel_for_nordic_row2_11 */
+        null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ more_keys_for_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* more_keys_for_cyrillic_ie */ "\u0451",
-        /* more_keys_for_nordic_row2_10 */ null,
+        /* keylabel_for_nordic_row1_11 ~ */
+        null, null, null, null,
+        /* ~ more_keys_for_nordic_row2_10 */
         // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA
         /* keylabel_for_east_slavic_row1_9 */ "\u0449",
         // U+044B: "ы" CYRILLIC SMALL LETTER YERU
@@ -2271,8 +2266,7 @@
         // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* more_keys_for_n */ "\u0146,\u00F1,\u0144,\u0144",
+        /* more_keys_for_n */ "\u0146,\u00F1,\u0144",
         /* label_to_alpha_key */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -2366,8 +2360,7 @@
         // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* more_keys_for_n */ "\u0146,\u00F1,\u0144,\u0144",
+        /* more_keys_for_n */ "\u0146,\u00F1,\u0144",
         /* label_to_alpha_key */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -2416,15 +2409,15 @@
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* label_to_alpha_key */ "\u0410\u0411\u0412",
         /* more_keys_for_y ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keylabel_for_nordic_row2_11 */
+        null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ more_keys_for_k */
         // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE
         /* more_keys_for_cyrillic_ie */ "\u0450",
-        /* more_keys_for_nordic_row2_10 ~ */
+        /* keylabel_for_nordic_row1_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, null, null, null, null,
         /* ~ more_keys_for_cyrillic_o */
         // U+0455: "ѕ" CYRILLIC SMALL LETTER DZE
         /* keylabel_for_south_slavic_row1_6 */ "\u0455",
@@ -2491,14 +2484,14 @@
         /* single_quotes */ "!text/single_9qm_rqm",
         /* more_keys_for_c ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ more_keys_for_k */
+        null,
+        /* ~ more_keys_for_cyrillic_ie */
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         /* keylabel_for_nordic_row1_11 */ "\u00E5",
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         /* keylabel_for_nordic_row2_10 */ "\u00F8",
         // U+00E6: "æ" LATIN SMALL LETTER AE
         /* keylabel_for_nordic_row2_11 */ "\u00E6",
-        /* more_keys_for_cyrillic_ie */ null,
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         /* more_keys_for_nordic_row2_10 */ "\u00F6",
         /* keylabel_for_east_slavic_row1_9 ~ */
@@ -2789,11 +2782,13 @@
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* label_to_alpha_key */ "\u0410\u0411\u0412",
         /* more_keys_for_y ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keylabel_for_nordic_row2_11 */
+        null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ more_keys_for_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* more_keys_for_cyrillic_ie */ "\u0451",
-        /* more_keys_for_nordic_row2_10 */ null,
+        /* keylabel_for_nordic_row1_11 ~ */
+        null, null, null, null,
+        /* ~ more_keys_for_nordic_row2_10 */
         // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA
         /* keylabel_for_east_slavic_row1_9 */ "\u0449",
         // U+044B: "ы" CYRILLIC SMALL LETTER YERU
@@ -2868,8 +2863,7 @@
         // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* more_keys_for_n */ "\u0148,\u0146,\u00F1,\u0144,\u0144",
+        /* more_keys_for_n */ "\u0148,\u0146,\u00F1,\u0144",
         /* label_to_alpha_key */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -2950,15 +2944,15 @@
         /* single_angle_quotes */ "!text/single_raqm_laqm",
         /* double_angle_quotes */ "!text/double_raqm_laqm",
         /* keylabel_for_currency ~ */
-        null, null, null, null, null, null,
-        /* ~ keylabel_for_nordic_row2_11 */
+        null, null, null,
+        /* ~ more_keys_for_k */
         // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE
         /* more_keys_for_cyrillic_ie */ "\u0450",
-        /* more_keys_for_nordic_row2_10 ~ */
+        /* keylabel_for_nordic_row1_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, null, null, null, null,
         /* ~ more_keys_for_cyrillic_o */
         // TODO: Move these to sr-Latn once we can handle IETF language tag with script name specified.
         // BEGIN: More keys definitions for Serbian (Latin)
@@ -3059,13 +3053,13 @@
         // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
         /* more_keys_for_r */ "\u0159",
         /* more_keys_for_k */ null,
+        /* more_keys_for_cyrillic_ie */ null,
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         /* keylabel_for_nordic_row1_11 */ "\u00E5",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         /* keylabel_for_nordic_row2_10 */ "\u00F6",
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         /* keylabel_for_nordic_row2_11 */ "\u00E4",
-        /* more_keys_for_cyrillic_ie */ null,
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+0153: "œ" LATIN SMALL LIGATURE OE
         /* more_keys_for_nordic_row2_10 */ "\u00F8,\u0153",
@@ -3441,7 +3435,7 @@
         // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
         // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
         // U+00AA: "ª" FEMININE ORDINAL INDICATOR
-        /* more_keys_for_a */ "\u00E0,\u00E1,\u00E2,\u00E3,\u00E4,\u00E5,\u00E6,\u00E3,\u00E5,\u0101,\u0103,\u0105,\u00AA",
+        /* more_keys_for_a */ "\u00E0,\u00E1,\u00E2,\u00E3,\u00E4,\u00E5,\u00E6,\u0101,\u0103,\u0105,\u00AA",
         // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
         // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
@@ -3548,7 +3542,7 @@
         // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
         // U+0138: "ĸ" LATIN SMALL LETTER KRA
         /* more_keys_for_k */ "\u0137,\u0138",
-        /* keylabel_for_nordic_row1_11 ~ */
+        /* more_keys_for_cyrillic_ie ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -3593,7 +3587,7 @@
         "hr", LANGUAGE_hr,    /*   9/ 19 Croatian */
         "hu", LANGUAGE_hu,    /*   9/ 19 Hungarian */
         "hy", LANGUAGE_hy_AM, /*   8/122 Armenian (Armenia) */
-        "is", LANGUAGE_is,    /*  13/ 25 Icelandic */
+        "is", LANGUAGE_is,    /*  10/ 15 Icelandic */
         "it", LANGUAGE_it,    /*   5/  5 Italian */
         "iw", LANGUAGE_iw,    /*  20/117 Hebrew */
         "ka", LANGUAGE_ka_GE, /*   3/ 11 Georgian (Georgia) */
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index b812f8f..65dad56 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -36,7 +36,7 @@
 #define DUMP_WORD_AND_SCORE(header) \
         do { char charBuf[50]; char prevWordCharBuf[50]; \
         INTS_TO_CHARS(getOutputWordBuf(), getNodeCodePointCount(), charBuf, NELEMS(charBuf)); \
-        INTS_TO_CHARS(mDicNodeState.mDicNodeStatePrevWord.mPrevWord, \
+        INTS_TO_CHARS(mDicNodeState.mDicNodeStatePrevWord.getPrevWordBuf(), \
                 mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength(), prevWordCharBuf, \
                 NELEMS(prevWordCharBuf)); \
         AKLOGI("#%8s, %5f, %5f, %5f, %5f, %s, %s, %d, %5f,", header, \
@@ -97,7 +97,7 @@
 
     DicNode(const DicNode &dicNode);
     DicNode &operator=(const DicNode &dicNode);
-    virtual ~DicNode() {}
+    ~DicNode() {}
 
     // Init for copy
     void initByCopy(const DicNode *const dicNode) {
@@ -130,22 +130,9 @@
                 NOT_A_PROBABILITY /* probability */, false /* isTerminal */,
                 true /* hasChildren */, false /* isBlacklistedOrNotAWord */,  0 /* depth */,
                 0 /* terminalDepth */);
-        // TODO: Move to dicNodeState?
-        mDicNodeState.mDicNodeStateOutput.init(); // reset for next word
-        mDicNodeState.mDicNodeStateInput.init(
-                &dicNode->mDicNodeState.mDicNodeStateInput, true /* resetTerminalDiffCost */);
-        mDicNodeState.mDicNodeStateScoring.init(
-                &dicNode->mDicNodeState.mDicNodeStateScoring);
-        mDicNodeState.mDicNodeStatePrevWord.init(
-                dicNode->mDicNodeState.mDicNodeStatePrevWord.getPrevWordCount() + 1,
-                dicNode->mDicNodeProperties.getProbability(),
+        mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
                 dicNode->mDicNodeProperties.getPtNodePos(),
-                dicNode->mDicNodeState.mDicNodeStatePrevWord.mPrevWord,
-                dicNode->mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength(),
-                dicNode->getOutputWordBuf(),
-                dicNode->mDicNodeProperties.getDepth(),
-                dicNode->mDicNodeState.mDicNodeStatePrevWord.getSecondWordFirstInputIndex(),
-                mDicNodeState.mDicNodeStateInput.getInputIndex(0) /* lastInputIndex */);
+                dicNode->mDicNodeProperties.getDepth());
         PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
     }
 
@@ -231,7 +218,7 @@
     }
 
     bool isFirstCharUppercase() const {
-        const int c = getOutputWordBuf()[0];
+        const int c = mDicNodeState.mDicNodeStateOutput.getCodePointAt(0);
         return CharUtils::isAsciiUpper(c);
     }
 
@@ -326,7 +313,7 @@
     void outputResult(int *dest) const {
         const uint16_t prevWordLength = mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength();
         const uint16_t currentDepth = getNodeCodePointCount();
-        DicNodeUtils::appendTwoWords(mDicNodeState.mDicNodeStatePrevWord.mPrevWord,
+        DicNodeUtils::appendTwoWords(mDicNodeState.mDicNodeStatePrevWord.getPrevWordBuf(),
                    prevWordLength, getOutputWordBuf(), currentDepth, dest);
         DUMP_WORD_AND_SCORE("OUTPUT");
     }
@@ -337,7 +324,7 @@
     // are concatenated together in mPrevWord - which contains a space at the end.
     int getTotalNodeSpaceCount() const {
         if (isFirstWord()) return 0;
-        return CharUtils::getSpaceCount(mDicNodeState.mDicNodeStatePrevWord.mPrevWord,
+        return CharUtils::getSpaceCount(mDicNodeState.mDicNodeStatePrevWord.getPrevWordBuf(),
                 mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength());
     }
 
@@ -389,7 +376,7 @@
     }
 
     AK_FORCE_INLINE const int *getOutputWordBuf() const {
-        return mDicNodeState.mDicNodeStateOutput.mCodePointsBuf;
+        return mDicNodeState.mDicNodeStateOutput.getCodePointBuf();
     }
 
     int getPrevCodePointG(int pointerId) const {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index a6ea68c..48752f2 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -16,7 +16,6 @@
 
 #include "suggest/core/dicnode/dic_node_utils.h"
 
-#include <algorithm>
 #include <cstring>
 
 #include "suggest/core/dicnode/dic_node.h"
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_vector.h b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
index 9364e77..cb28e57 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_vector.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
@@ -32,10 +32,10 @@
 #else
     static const int DEFAULT_NODES_SIZE_FOR_OPTIMIZATION = 60;
 #endif
-    AK_FORCE_INLINE DicNodeVector() : mDicNodes(0), mLock(false), mEmptyNode() {}
+    AK_FORCE_INLINE DicNodeVector() : mDicNodes(), mLock(false) {}
 
     // Specify the capacity of the vector
-    AK_FORCE_INLINE DicNodeVector(const int size) : mDicNodes(0), mLock(false), mEmptyNode() {
+    AK_FORCE_INLINE DicNodeVector(const int size) : mDicNodes(), mLock(false) {
         mDicNodes.reserve(size);
     }
 
@@ -52,13 +52,9 @@
         return static_cast<int>(mDicNodes.size());
     }
 
-    bool exceeds(const size_t limit) const {
-        return mDicNodes.size() >= limit;
-    }
-
     void pushPassingChild(DicNode *dicNode) {
         ASSERT(!mLock);
-        mDicNodes.push_back(mEmptyNode);
+        mDicNodes.emplace_back();
         mDicNodes.back().initAsPassingChild(dicNode);
     }
 
@@ -67,7 +63,7 @@
             const bool hasChildren, const bool isBlacklistedOrNotAWord,
             const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
         ASSERT(!mLock);
-        mDicNodes.push_back(mEmptyNode);
+        mDicNodes.emplace_back();
         mDicNodes.back().initAsChild(dicNode, ptNodePos, childrenPtNodeArrayPos, probability,
                 isTerminal, hasChildren, isBlacklistedOrNotAWord, mergedNodeCodePointCount,
                 mergedNodeCodePoints);
@@ -80,14 +76,13 @@
 
     DicNode *front() {
         ASSERT(1 <= static_cast<int>(mDicNodes.size()));
-        return &mDicNodes[0];
+        return &mDicNodes.front();
     }
 
  private:
     DISALLOW_COPY_AND_ASSIGN(DicNodeVector);
     std::vector<DicNode> mDicNodes;
     bool mLock;
-    DicNode mEmptyNode;
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_VECTOR_H
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
index c41a724..ab02e61 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
@@ -33,7 +33,7 @@
               mIsTerminal(false), mHasChildrenPtNodes(false), mIsBlacklistedOrNotAWord(false),
               mDepth(0), mLeavingDepth(0) {}
 
-    virtual ~DicNodeProperties() {}
+    ~DicNodeProperties() {}
 
     // Should be called only once per DicNode is initialized.
     void init(const int pos, const int childrenPos, const int nodeCodePoint, const int probability,
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state.h
index b0fddb7..a416675 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state.h
@@ -37,7 +37,18 @@
               mDicNodeStateScoring() {
     }
 
-    virtual ~DicNodeState() {}
+    ~DicNodeState() {}
+
+    DicNodeState &operator=(const DicNodeState& src) {
+        init(&src);
+        return *this;
+    }
+
+    DicNodeState(const DicNodeState& src)
+            : mDicNodeStateInput(), mDicNodeStateOutput(), mDicNodeStatePrevWord(),
+              mDicNodeStateScoring() {
+        init(&src);
+    }
 
     // Init with prevWordPos
     void init(const int prevWordPos) {
@@ -47,6 +58,24 @@
         mDicNodeStateScoring.init();
     }
 
+    // Init with previous word.
+    void initAsRootWithPreviousWord(const DicNodeState *prevWordDicNodeState,
+            const int prevWordPos, const int prevWordCodePointCount) {
+        mDicNodeStateOutput.init(); // reset for next word
+        mDicNodeStateInput.init(
+                &prevWordDicNodeState->mDicNodeStateInput, true /* resetTerminalDiffCost */);
+        mDicNodeStateScoring.init(&prevWordDicNodeState->mDicNodeStateScoring);
+        mDicNodeStatePrevWord.init(
+                prevWordDicNodeState->mDicNodeStatePrevWord.getPrevWordCount() + 1,
+                prevWordPos,
+                prevWordDicNodeState->mDicNodeStatePrevWord.getPrevWordBuf(),
+                prevWordDicNodeState->mDicNodeStatePrevWord.getPrevWordLength(),
+                prevWordDicNodeState->mDicNodeStateOutput.getCodePointBuf(),
+                prevWordCodePointCount,
+                prevWordDicNodeState->mDicNodeStatePrevWord.getSecondWordFirstInputIndex(),
+                prevWordDicNodeState->mDicNodeStateInput.getInputIndex(0) /* lastInputIndex */);
+    }
+
     // Init by copy
     AK_FORCE_INLINE void init(const DicNodeState *const src) {
         mDicNodeStateInput.init(&src->mDicNodeStateInput);
@@ -62,11 +91,6 @@
         mDicNodeStateOutput.addMergedNodeCodePoints(
                 mergedNodeCodePointCount, mergedNodeCodePoints);
     }
-
- private:
-    // Caution!!!
-    // Use a default copy constructor and an assign operator because shallow copies are ok
-    // for this class
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_STATE_H
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_input.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_input.h
index bbd9435..3d78811 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_input.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_input.h
@@ -25,7 +25,7 @@
 class DicNodeStateInput {
  public:
     DicNodeStateInput() {}
-    virtual ~DicNodeStateInput() {}
+    ~DicNodeStateInput() {}
 
     // TODO: Merge into DicNodeStatePrevWord::truncate
     void truncate(const int commitPoint) {
@@ -89,9 +89,8 @@
     }
 
  private:
-    // Caution!!!
-    // Use a default copy constructor and an assign operator because shallow copies are ok
-    // for this class
+    DISALLOW_COPY_AND_ASSIGN(DicNodeStateInput);
+
     int mInputIndex[MAX_POINTER_COUNT_G];
     int mPrevCodePoint[MAX_POINTER_COUNT_G];
     float mTerminalDiffCost[MAX_POINTER_COUNT_G];
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h
index abafc0e..bdb182c 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h
@@ -27,11 +27,9 @@
 
 class DicNodeStateOutput {
  public:
-    DicNodeStateOutput() : mOutputtedCodePointCount(0) {
-        init();
-    }
+    DicNodeStateOutput() : mOutputtedCodePointCount(0) {}
 
-    virtual ~DicNodeStateOutput() {}
+    ~DicNodeStateOutput() {}
 
     void init() {
         mOutputtedCodePointCount = 0;
@@ -63,19 +61,19 @@
         }
     }
 
-    // TODO: Remove
     int getCodePointAt(const int index) const {
         return mCodePointsBuf[index];
     }
 
-    // TODO: Move to private
-    int mCodePointsBuf[MAX_WORD_LENGTH];
+    const int *getCodePointBuf() const {
+        return mCodePointsBuf;
+    }
 
  private:
-    // Caution!!!
-    // Use a default copy constructor and an assign operator because shallow copies are ok
-    // for this class
+    DISALLOW_COPY_AND_ASSIGN(DicNodeStateOutput);
+
     uint16_t mOutputtedCodePointCount;
+    int mCodePointsBuf[MAX_WORD_LENGTH];
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_STATE_OUTPUT_H
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
index 7868f78..f2b1ce8 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
@@ -30,29 +30,18 @@
 class DicNodeStatePrevWord {
  public:
     AK_FORCE_INLINE DicNodeStatePrevWord()
-            : mPrevWordCount(0), mPrevWordLength(0), mPrevWordStart(0), mPrevWordProbability(0),
-              mPrevWordPtNodePos(NOT_A_DICT_POS), mSecondWordFirstInputIndex(NOT_AN_INDEX) {
-        memset(mPrevWord, 0, sizeof(mPrevWord));
-    }
+            : mPrevWordCount(0), mPrevWordLength(0), mPrevWordStart(0),
+              mPrevWordPtNodePos(NOT_A_DICT_POS), mSecondWordFirstInputIndex(NOT_AN_INDEX) {}
 
-    virtual ~DicNodeStatePrevWord() {}
-
-    void init() {
-        mPrevWordLength = 0;
-        mPrevWordCount = 0;
-        mPrevWordStart = 0;
-        mPrevWordProbability = -1;
-        mPrevWordPtNodePos = NOT_A_DICT_POS;
-        mSecondWordFirstInputIndex = NOT_AN_INDEX;
-    }
+    ~DicNodeStatePrevWord() {}
 
     void init(const int prevWordNodePos) {
         mPrevWordLength = 0;
         mPrevWordCount = 0;
         mPrevWordStart = 0;
-        mPrevWordProbability = -1;
         mPrevWordPtNodePos = prevWordNodePos;
         mSecondWordFirstInputIndex = NOT_AN_INDEX;
+        mPrevWord[0] = 0;
     }
 
     // Init by copy
@@ -60,18 +49,15 @@
         mPrevWordLength = prevWord->mPrevWordLength;
         mPrevWordCount = prevWord->mPrevWordCount;
         mPrevWordStart = prevWord->mPrevWordStart;
-        mPrevWordProbability = prevWord->mPrevWordProbability;
         mPrevWordPtNodePos = prevWord->mPrevWordPtNodePos;
         mSecondWordFirstInputIndex = prevWord->mSecondWordFirstInputIndex;
         memmove(mPrevWord, prevWord->mPrevWord, prevWord->mPrevWordLength * sizeof(mPrevWord[0]));
     }
 
-    void init(const int16_t prevWordCount, const int16_t prevWordProbability,
-            const int prevWordNodePos, const int *const src0, const int16_t length0,
-            const int *const src1, const int16_t length1,
+    void init(const int16_t prevWordCount, const int prevWordNodePos, const int *const src0,
+            const int16_t length0, const int *const src1, const int16_t length1,
             const int prevWordSecondWordFirstInputIndex, const int lastInputIndex) {
         mPrevWordCount = std::min(prevWordCount, static_cast<int16_t>(MAX_RESULTS));
-        mPrevWordProbability = prevWordProbability;
         mPrevWordPtNodePos = prevWordNodePos;
         int twoWordsLen =
                 DicNodeUtils::appendTwoWords(src0, length0, src1, length1, mPrevWord);
@@ -137,19 +123,19 @@
         return true;
     }
 
-    // TODO: Move to private
-    int mPrevWord[MAX_WORD_LENGTH];
+    const int *getPrevWordBuf() const {
+        return mPrevWord;
+    }
 
  private:
-    // Caution!!!
-    // Use a default copy constructor and an assign operator because shallow copies are ok
-    // for this class
+    DISALLOW_COPY_AND_ASSIGN(DicNodeStatePrevWord);
+
     int16_t mPrevWordCount;
     int16_t mPrevWordLength;
     int16_t mPrevWordStart;
-    int16_t mPrevWordProbability;
     int mPrevWordPtNodePos;
     int mSecondWordFirstInputIndex;
+    int mPrevWord[MAX_WORD_LENGTH];
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_STATE_PREVWORD_H
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
index 18b7d73..458eac8 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
@@ -37,7 +37,7 @@
               mNormalizedCompoundDistanceAfterFirstWord(MAX_VALUE_FOR_WEIGHTING) {
     }
 
-    virtual ~DicNodeStateScoring() {}
+    ~DicNodeStateScoring() {}
 
     void init() {
         mEditCorrectionCount = 0;
@@ -175,9 +175,8 @@
     }
 
  private:
-    // Caution!!!
-    // Use a default copy constructor and an assign operator because shallow copies are ok
-    // for this class
+    DISALLOW_COPY_AND_ASSIGN(DicNodeStateScoring);
+
     DoubleLetterLevel mDoubleLetterLevel;
     DigraphUtils::DigraphCodePointIndex mDigraphIndex;
 
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index ffa96e1..c26e3aa 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -37,7 +37,7 @@
 Dictionary::Dictionary(JNIEnv *env, DictionaryStructureWithBufferPolicy::StructurePolicyPtr
         dictionaryStructureWithBufferPolicy)
         : mDictionaryStructureWithBufferPolicy(std::move(dictionaryStructureWithBufferPolicy)),
-          mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy.get())),
+          mBigramDictionary(mDictionaryStructureWithBufferPolicy.get()),
           mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
           mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
     logDictionaryInfo(env);
@@ -78,7 +78,7 @@
         SuggestionResults *const outSuggestionResults) const {
     TimeKeeper::setCurrentTime();
     if (length <= 0) return;
-    mBigramDictionary->getPredictions(word, length, outSuggestionResults);
+    mBigramDictionary.getPredictions(word, length, outSuggestionResults);
 }
 
 int Dictionary::getProbability(const int *word, int length) const {
@@ -94,7 +94,7 @@
 int Dictionary::getBigramProbability(const int *word0, int length0, const int *word1,
         int length1) const {
     TimeKeeper::setCurrentTime();
-    return mBigramDictionary->getBigramProbability(word0, length0, word1, length1);
+    return mBigramDictionary.getBigramProbability(word0, length0, word1, length1);
 }
 
 void Dictionary::addUnigramWord(const int *const word, const int length, const int probability,
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index 2dea9ff..ce032fc 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -109,14 +109,13 @@
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
 
-    typedef std::unique_ptr<BigramDictionary> BigramDictionaryPtr;
     typedef std::unique_ptr<SuggestInterface> SuggestInterfacePtr;
 
     static const int HEADER_ATTRIBUTE_BUFFER_SIZE;
 
     const DictionaryStructureWithBufferPolicy::StructurePolicyPtr
             mDictionaryStructureWithBufferPolicy;
-    const BigramDictionaryPtr mBigramDictionary;
+    const BigramDictionary mBigramDictionary;
     const SuggestInterfacePtr mGestureSuggest;
     const SuggestInterfacePtr mTypingSuggest;
 
diff --git a/native/jni/src/suggest/core/result/suggested_word.h b/native/jni/src/suggest/core/result/suggested_word.h
index 48b29d6..258a40e 100644
--- a/native/jni/src/suggest/core/result/suggested_word.h
+++ b/native/jni/src/suggest/core/result/suggested_word.h
@@ -30,9 +30,9 @@
      public:
         bool operator()(const SuggestedWord &left, const SuggestedWord &right) {
             if (left.getScore() != right.getScore()) {
-                return left.getScore() < right.getScore();
+                return left.getScore() > right.getScore();
             }
-            return left.getCodePointCount() > right.getCodePointCount();
+            return left.getCodePointCount() < right.getCodePointCount();
         }
 
      private:
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index c3b6703..f60a210 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -248,17 +248,16 @@
     if (dicNode->shouldBeFilteredBySafetyNetForBigram()) {
         return;
     }
+    if (!dicNode->hasMatchedOrProximityCodePoints()) {
+        return;
+    }
     // Create a non-cached node here.
-    DicNode terminalDicNode;
-    DicNodeUtils::initByCopy(dicNode, &terminalDicNode);
+    DicNode terminalDicNode(*dicNode);
     if (TRAVERSAL->needsToTraverseAllUserInput()
             && dicNode->getInputIndex(0) < traverseSession->getInputSize()) {
         Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_TERMINAL_INSERTION, traverseSession, 0,
                 &terminalDicNode, traverseSession->getMultiBigramMap());
     }
-    if (!dicNode->hasMatchedOrProximityCodePoints()) {
-        return;
-    }
     Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_TERMINAL, traverseSession, 0,
             &terminalDicNode, traverseSession->getMultiBigramMap());
     traverseSession->getDicTraverseCache()->copyPushTerminal(&terminalDicNode);
@@ -375,6 +374,7 @@
         DicNode *dicNode) const {
     const int16_t pointIndex = dicNode->getInputIndex(0);
     DicNodeVector childDicNodes1;
+    DicNodeVector childDicNodes2;
     DicNodeUtils::getAllChildDicNodes(dicNode, traverseSession->getDictionaryStructurePolicy(),
             &childDicNodes1);
     const int childSize1 = childDicNodes1.getSizeAndLock();
@@ -386,7 +386,7 @@
             continue;
         }
         if (childDicNodes1[i]->hasChildren()) {
-            DicNodeVector childDicNodes2;
+            childDicNodes2.clear();
             DicNodeUtils::getAllChildDicNodes(childDicNodes1[i],
                     traverseSession->getDictionaryStructurePolicy(), &childDicNodes2);
             const int childSize2 = childDicNodes2.getSizeAndLock();
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index 84a6ccf..4e795f8 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -349,13 +349,14 @@
         // Skip the entry if the entry has been deleted. This never happens for ver2 dicts.
         if (bigramsIt.getBigramPos() != NOT_A_DICT_POS) {
             int word1Probability = NOT_A_PROBABILITY;
-            int word1CodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
+            const int word1CodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
                     bigramsIt.getBigramPos(), MAX_WORD_LENGTH, bigramWord1CodePoints,
                     &word1Probability);
-            std::vector<int> word1(bigramWord1CodePoints,
+            const std::vector<int> word1(bigramWord1CodePoints,
                     bigramWord1CodePoints + word1CodePointCount);
-            bigrams.push_back(WordProperty::BigramProperty(&word1, bigramsIt.getProbability(),
-                    NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */));
+            const int probability = getProbability(word1Probability, bigramsIt.getProbability());
+            bigrams.emplace_back(&word1, probability,
+                    NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */);
         }
     }
     // Fetch shortcut information.
@@ -371,12 +372,11 @@
             hasNext = ShortcutListReadingUtils::hasNext(shortcutFlags);
             const int shortcutTargetLength = ShortcutListReadingUtils::readShortcutTarget(
                     mDictRoot, MAX_WORD_LENGTH, shortcutTargetCodePoints, &shortcutPos);
-            std::vector<int> shortcutTarget(shortcutTargetCodePoints,
+            const std::vector<int> shortcutTarget(shortcutTargetCodePoints,
                     shortcutTargetCodePoints + shortcutTargetLength);
             const int shortcutProbability =
                     ShortcutListReadingUtils::getProbabilityFromFlags(shortcutFlags);
-            shortcuts.push_back(
-                    WordProperty::ShortcutProperty(&shortcutTarget, shortcutProbability));
+            shortcuts.emplace_back(&shortcutTarget, shortcutProbability);
         }
     }
     return WordProperty(&codePointVector, ptNodeParams.isNotAWord(),
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 1a38a27..107ddab 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -382,16 +382,16 @@
             const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
                     word1TerminalPtNodePos, MAX_WORD_LENGTH, bigramWord1CodePoints,
                     &word1Probability);
-            std::vector<int> word1(bigramWord1CodePoints,
+            const std::vector<int> word1(bigramWord1CodePoints,
                     bigramWord1CodePoints + codePointCount);
             const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo();
             const int probability = bigramEntry.hasHistoricalInfo() ?
                     ForgettingCurveUtils::decodeProbability(
                             bigramEntry.getHistoricalInfo(), mHeaderPolicy) :
-                    bigramEntry.getProbability();
-            bigrams.push_back(WordProperty::BigramProperty(&word1, probability,
+                    getProbability(word1Probability, bigramEntry.getProbability());
+            bigrams.emplace_back(&word1, probability,
                     historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-                    historicalInfo->getCount()));
+                    historicalInfo->getCount());
         }
     }
     // Fetch shortcut information.
@@ -407,8 +407,8 @@
             int shortcutProbability = NOT_A_PROBABILITY;
             shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
                     &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
-            std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
-            shortcuts.push_back(WordProperty::ShortcutProperty(&target, shortcutProbability));
+            const std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
+            shortcuts.emplace_back(&target, shortcutProbability);
         }
     }
     return WordProperty(&codePointVector, ptNodeParams.isNotAWord(),
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp
index 9441a75..fb80f38 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp
@@ -68,6 +68,9 @@
         if (dirent->d_type == DT_DIR) {
             continue;
         }
+        if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) {
+            continue;
+        }
         const int filePathBufSize = getFilePathBufSize(dirPath, dirent->d_name);
         char filePath[filePathBufSize];
         getFilePath(dirPath, dirent->d_name, filePathBufSize, filePath);
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
index 3db00ad..7c86b7d 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -162,9 +162,8 @@
         if (probability < ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY) {
             return false;
         }
-        const int c = dicNode->getOutputWordBuf()[0];
         const bool shortCappedWord = dicNode->getNodeCodePointCount()
-                < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && CharUtils::isAsciiUpper(c);
+                < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && dicNode->isFirstCharUppercase();
         return !shortCappedWord
                 || probability >= ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
     }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java
index be3ed12..b81061a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java
@@ -28,13 +28,12 @@
  * The generic upper case alphabet keyboard layout.
  */
 public final class AlphabetShifted extends LayoutBase {
-    public static ExpectedKey[][] getAlphabet(final ExpectedKey[][] lowerCaseKeyboard,
+    public static ExpectedKey[][] getDefaultLayout(final ExpectedKey[][] lowerCaseKeyboard,
             final Locale locale) {
-        final ExpectedKey[][] upperCaseKeyboard = ExpectedKeyboardBuilder.toUpperCase(
-                lowerCaseKeyboard, locale);
-        return new ExpectedKeyboardBuilder(upperCaseKeyboard)
-                .replaceKeyOfAll(SHIFT_KEY, SHIFTED_SHIFT_KEY)
-                .build();
+        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(lowerCaseKeyboard);
+        builder.toUpperCase(locale);
+        builder.replaceKeysOfAll(SHIFT_KEY, SHIFTED_SHIFT_KEY);
+        return builder.build();
     }
 
     // Icon id.
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
index f7179b7..325b784 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
@@ -24,8 +24,10 @@
  * The QWERTY alphabet keyboard.
  */
 public final class Qwerty extends LayoutBase {
-    public static ExpectedKey[][] getAlphabet(final boolean isPhone) {
-        return toCommonAlphabet(ALPHABET_COMMON, isPhone);
+    public static final String LAYOUT_NAME = "qwerty";
+
+    public static ExpectedKey[][] getLayout(final boolean isPhone) {
+        return getDefaultAlphabetLayout(ALPHABET_COMMON, isPhone);
     }
 
     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder(10, 9, 7, 3)
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
index 03d7f07..6fcfa05 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
@@ -25,15 +25,87 @@
  * The symbols keyboard layout.
  */
 public final class Symbols extends LayoutBase {
-    public static ExpectedKey[][] getSymbols(final boolean isPhone) {
+    public static ExpectedKey[][] getLayout(final boolean isPhone) {
         return isPhone ? toPhoneSymbol(SYMBOLS_COMMON) : toTabletSymbols(SYMBOLS_COMMON);
     }
 
+    public static ExpectedKey[][] getDefaultLayout(final boolean isPhone) {
+        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(getLayout(isPhone));
+        builder.replaceKeyOfLabel(CURRENCY, Symbols.CURRENCY_DOLLAR);
+        builder.replaceKeyOfLabel(DOUBLE_QUOTE,
+                key("\"", join(Symbols.DOUBLE_QUOTES_9LR, Symbols.DOUBLE_ANGLE_QUOTES_LR)));
+        builder.replaceKeyOfLabel(SINGLE_QUOTE,
+                key("'", join(Symbols.SINGLE_QUOTES_9LR, Symbols.SINGLE_ANGLE_QUOTES_LR)));
+        return builder.build();
+    }
+
     // Functional keys.
     public static final ExpectedKey ALPHABET_KEY = key("ABC", Constants.CODE_SWITCH_ALPHA_SYMBOL);
     public static final ExpectedKey SYMBOLS_SHIFT_KEY = key("= \\ <", Constants.CODE_SHIFT);
     public static final ExpectedKey TABLET_SYMBOLS_SHIFT_KEY = key("~ [ <", Constants.CODE_SHIFT);
 
+    // Variations of the "currency" key on the 2nd row.
+    public static final String CURRENCY = "currency";
+    // U+00A2: "¢" CENT SIGN
+    // U+00A3: "£" POUND SIGN
+    // U+00A5: "¥" YEN SIGN
+    // U+20AC: "€" EURO SIGN
+    // U+20B1: "₱" PESO SIGN
+    public static final ExpectedKey DOLLAR_SIGN = key("$");
+    public static final ExpectedKey CENT_SIGN = key("\u00A2");
+    public static final ExpectedKey POUND_SIGN = key("\u00A3");
+    public static final ExpectedKey YEN_SIGN = key("\u00A5");
+    public static final ExpectedKey EURO_SIGN = key("\u20AC");
+    public static final ExpectedKey PESO_SIGN = key("\u20B1");
+    public static final ExpectedKey CURRENCY_DOLLAR = key("$",
+            CENT_SIGN, POUND_SIGN, EURO_SIGN, YEN_SIGN, PESO_SIGN);
+    public static final ExpectedKey CURRENCY_EURO = key("\u20AC",
+            CENT_SIGN, POUND_SIGN, DOLLAR_SIGN, YEN_SIGN, PESO_SIGN);
+
+    // Variations of the "double quote" key's "more keys" on the 3rd row.
+    public static final String DOUBLE_QUOTE = "double_quote";
+    // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+    // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+    // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+    static final ExpectedKey DQUOTE_LEFT = key("\u201C");
+    static final ExpectedKey DQUOTE_RIGHT = key("\u201D");
+    static final ExpectedKey DQUOTE_LOW9 = key("\u201E");
+    public static ExpectedKey[] DOUBLE_QUOTES_9LR = { DQUOTE_LOW9, DQUOTE_LEFT, DQUOTE_RIGHT };
+    public static ExpectedKey[] DOUBLE_QUOTES_R9L = { DQUOTE_RIGHT, DQUOTE_LOW9, DQUOTE_LEFT };
+    public static ExpectedKey[] DOUBLE_QUOTES_L9R = { DQUOTE_LEFT, DQUOTE_LOW9, DQUOTE_RIGHT };
+    public static ExpectedKey[] DOUBLE_QUOTES_LR9 = { DQUOTE_LEFT, DQUOTE_RIGHT, DQUOTE_LOW9 };
+    // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    private static final ExpectedKey DAQUOTE_LEFT = key("\u00AB");
+    private static final ExpectedKey DAQUOTE_RIGHT = key("\u00BB");
+    private static final ExpectedKey DAQUOTE_LEFT_RTL = key("\u00AB", "\u00BB");
+    private static final ExpectedKey DAQUOTE_RIGHT_RTL = key("\u00BB", "\u00AB");
+    public static ExpectedKey[] DOUBLE_ANGLE_QUOTES_LR = { DAQUOTE_LEFT, DAQUOTE_RIGHT };
+    public static ExpectedKey[] DOUBLE_ANGLE_QUOTES_RL = { DAQUOTE_RIGHT, DAQUOTE_LEFT };
+    public static ExpectedKey[] DOUBLE_ANGLE_QUOTES_RTL = { DAQUOTE_LEFT_RTL, DAQUOTE_RIGHT_RTL };
+
+    // Variations of the "single quote" key's "more keys" on the 3rd row.
+    public static final String SINGLE_QUOTE = "single_quote";
+    // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+    // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+    // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+    static final ExpectedKey SQUOTE_LEFT = key("\u2018");
+    static final ExpectedKey SQUOTE_RIGHT = key("\u2019");
+    static final ExpectedKey SQUOTE_LOW9 = key("\u201A");
+    public static ExpectedKey[] SINGLE_QUOTES_9LR = { SQUOTE_LOW9, SQUOTE_LEFT, SQUOTE_RIGHT };
+    public static ExpectedKey[] SINGLE_QUOTES_R9L = { SQUOTE_RIGHT, SQUOTE_LOW9, SQUOTE_LEFT };
+    public static ExpectedKey[] SINGLE_QUOTES_L9R = { SQUOTE_LEFT, SQUOTE_LOW9, SQUOTE_RIGHT };
+    public static ExpectedKey[] SINGLE_QUOTES_LR9 = { SQUOTE_LEFT, SQUOTE_RIGHT, SQUOTE_LOW9 };
+    // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    private static final ExpectedKey SAQUOTE_LEFT = key("\u2039");
+    private static final ExpectedKey SAQUOTE_RIGHT = key("\u203A");
+    private static final ExpectedKey SAQUOTE_LEFT_RTL = key("\u2039", "\u203A");
+    private static final ExpectedKey SAQUOTE_RIGHT_RTL = key("\u203A", "\u2039");
+    public static ExpectedKey[] SINGLE_ANGLE_QUOTES_LR = { SAQUOTE_LEFT, SAQUOTE_RIGHT };
+    public static ExpectedKey[] SINGLE_ANGLE_QUOTES_RL = { SAQUOTE_RIGHT, SAQUOTE_LEFT };
+    public static ExpectedKey[] SINGLE_ANGLE_QUOTES_RTL = { SAQUOTE_LEFT_RTL, SAQUOTE_RIGHT_RTL };
+
     // Common symbols keyboard layout.
     public static final ExpectedKey[][] SYMBOLS_COMMON = new ExpectedKeyboardBuilder(10, 9, 7, 5)
             .setLabelsOfRow(1, "1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
@@ -59,13 +131,7 @@
             // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N
             // U+2205: "∅" EMPTY SET
             .setMoreKeysOf("0", "\u207F", "\u2205")
-            .setLabelsOfRow(2, "@", "#", "$", "%", "&", "-", "+", "(", ")")
-            // U+00A2: "¢" CENT SIGN
-            // U+00A3: "£" POUND SIGN
-            // U+20AC: "€" EURO SIGN
-            // U+00A5: "¥" YEN SIGN
-            // U+20B1: "₱" PESO SIGN
-            .setMoreKeysOf("$", "\u00A2", "\u00A3", "\u20AC", "\u00A5", "\u20B1")
+            .setLabelsOfRow(2, "@", "#", CURRENCY, "%", "&", "-", "+", "(", ")")
             // U+2030: "‰" PER MILLE SIGN
             .setMoreKeysOf("%", "\u2030")
             // U+2013: "–" EN DASH
@@ -76,23 +142,11 @@
             .setMoreKeysOf("+", "\u00B1")
             .setMoreKeysOf("(", "<", "{", "[")
             .setMoreKeysOf(")", ">", "}", "]")
-            .setLabelsOfRow(3, "*", "\"", "'", ":", ";", "!", "?")
+            .setLabelsOfRow(3, "*", DOUBLE_QUOTE, SINGLE_QUOTE, ":", ";", "!", "?")
             // U+2020: "†" DAGGER
             // U+2021: "‡" DOUBLE DAGGER
             // U+2605: "★" BLACK STAR
             .setMoreKeysOf("*", "\u2020", "\u2021", "\u2605")
-            // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
-            // U+201C: "“" LEFT DOUBLE QUOTATION MARK
-            // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
-            // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
-            // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
-            .setMoreKeysOf("\"", "\u201E", "\u201C", "\u201D", "\u00AB", "\u00BB")
-            // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
-            // U+2018: "‘" LEFT SINGLE QUOTATION MARK
-            // U+2019: "’" RIGHT SINGLE QUOTATION MARK
-            // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
-            // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
-            .setMoreKeysOf("'", "\u201A", "\u2018", "\u2019", "\u2039", "\u203A")
             // U+00A1: "¡" INVERTED EXCLAMATION MARK
             .setMoreKeysOf("!", "\u00A1")
             // U+00BF: "¿" INVERTED QUESTION MARK
@@ -123,65 +177,4 @@
                 .addKeysOnTheRightOfRow(4, EMOJI_KEY)
                 .build();
     }
-
-    // Helper method to add currency symbols for Euro.
-    public static ExpectedKeyboardBuilder euro(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+20AC: "€" EURO SIGN
-                // U+00A2: "¢" CENT SIGN
-                // U+00A3: "£" POUND SIGN
-                // U+00A5: "¥" YEN SIGN
-                // U+20B1: "₱" PESO SIGN
-                .replaceKeyOfLabel("$", key("\u20AC",
-                        moreKey("\u00A2"), moreKey("\u00A3"), moreKey("$"),
-                        moreKey("\u00A5"), moreKey("\u20B1")));
-    }
-
-    // Helper method to add single quotes "more keys".
-    // "9LLR" means "9-low/Left quotation marks, Left/Right-pointing angle quotation marks".
-    public static ExpectedKeyboardBuilder singleQuotes9LLR(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+2019: "’" RIGHT SINGLE QUOTATION MARK
-                // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
-                // U+2018: "‘" LEFT SINGLE QUOTATION MARK
-                // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
-                // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
-                .setMoreKeysOf("'", "\u2019", "\u201A", "\u2018", "\u2039", "\u203A");
-    }
-
-    // Helper method to add single quotes "more keys".
-    // "9LLR" means "9-low/Left quotation marks, Right/Left-pointing angle quotation marks".
-    public static ExpectedKeyboardBuilder singleQuotes9LRL(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+2019: "’" RIGHT SINGLE QUOTATION MARK
-                // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
-                // U+2018: "‘" LEFT SINGLE QUOTATION MARK
-                // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
-                // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
-                .setMoreKeysOf("'", "\u2019", "\u201A", "\u2018", "\u203A", "\u2039");
-    }
-
-    // Helper method to add double quotes "more keys".
-    // "9LLR" means "9-low/Left quotation marks, Left/Right-pointing angle quotation marks".
-    public static ExpectedKeyboardBuilder doubleQuotes9LLR(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
-                // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
-                // U+201C: "“" LEFT DOUBLE QUOTATION MARK
-                // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
-                // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
-                .setMoreKeysOf("\"", "\u201D", "\u201E", "\u201C", "\u00AB", "\u00BB");
-    }
-
-    // Helper method to add double quotes "more keys".
-    // "9LLR" means "9-low/Left quotation marks, Right/Left-pointing angle quotation marks".
-    public static ExpectedKeyboardBuilder doubleQuotes9LRL(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
-                // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
-                // U+201C: "“" LEFT DOUBLE QUOTATION MARK
-                // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
-                // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
-                .setMoreKeysOf("\"", "\u201D", "\u201E", "\u201C", "\u00BB", "\u00AB");
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
index 368f9db..4d9ae43 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
@@ -25,17 +25,33 @@
  * The symbols shifted keyboard layout.
  */
 public final class SymbolsShifted extends LayoutBase {
-    public static ExpectedKey[][] getSymbolsShifted(final boolean isPhone) {
+    public static ExpectedKey[][] getLayout(final boolean isPhone) {
         return isPhone ? toPhoneSymbolsShifted(SYMBOLS_SHIFTED_COMMON)
                 : toTabletSymbolsShifted(SYMBOLS_SHIFTED_COMMON);
     }
 
+    public static ExpectedKey[][] getDefaultLayout(final boolean isPhone) {
+        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(getLayout(isPhone));
+        builder.replaceKeyOfLabel(OTHER_CURRENCIES, SymbolsShifted.CURRENCIES_OTHER_THAN_DOLLAR);
+        return builder.build();
+    }
+
     // Functional key.
     public static final ExpectedKey BACK_TO_SYMBOLS_KEY = key("?123", Constants.CODE_SHIFT);
 
+    // Variations of the "other currencies" keys on the 2rd row.
+    public static final String OTHER_CURRENCIES = "other_currencies";
+    public static final ExpectedKey[] CURRENCIES_OTHER_THAN_DOLLAR = {
+        Symbols.POUND_SIGN, Symbols.CENT_SIGN, Symbols.EURO_SIGN, Symbols.YEN_SIGN
+    };
+    public static final ExpectedKey[] CURRENCIES_OTHER_THAN_EURO = {
+        Symbols.POUND_SIGN, Symbols.YEN_SIGN, key(Symbols.DOLLAR_SIGN, Symbols.CENT_SIGN),
+        Symbols.CENT_SIGN
+    };
+
     // Common symbols shifted keyboard layout.
     public static final ExpectedKey[][] SYMBOLS_SHIFTED_COMMON =
-            new ExpectedKeyboardBuilder(10, 9, 7, 5)
+            new ExpectedKeyboardBuilder(10, 1 /* other_currencies */ + 5, 7, 5)
             // U+0060: "`" GRAVE ACCENT
             // U+2022: "•" BULLET
             // U+221A: "√" SQUARE ROOT
@@ -60,14 +76,8 @@
             // U+00B6: "¶" PILCROW SIGN
             // U+00A7: "§" SECTION SIGN
             .setMoreKeysOf("\u00B6", "\u00A7")
-            // U+00A3: "£" POUND SIGN
-            // U+00A2: "¢" CENT SIGN
-            // U+20AC: "€" EURO SIGN
-            // U+00A5: "¥" YEN SIGN
             // U+00B0: "°" DEGREE SIGN
-            .setLabelsOfRow(2,
-                    "\u00A3", "\u00A2", "\u20AC", "\u00A5", "^",
-                    "\u00B0", "=", "{", "}")
+            .setLabelsOfRow(2, OTHER_CURRENCIES, "^", "\u00B0", "=", "{", "}")
             // U+2191: "↑" UPWARDS ARROW
             // U+2193: "↓" DOWNWARDS ARROW
             // U+2190: "←" LEFTWARDS ARROW
@@ -125,18 +135,4 @@
                 .addKeysOnTheRightOfRow(4, EMOJI_KEY)
                 .build();
     }
-
-    // Helper method to add currency symbols for Euro.
-    public static ExpectedKeyboardBuilder euro(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+00A5: "¥" YEN SIGN
-                // U+00A2: "¢" CENT SIGN
-                .replaceKeyOfLabel("\u00A5", key("\u00A2"))
-                // U+20AC: "€" EURO SIGN
-                // U+00A2: "¢" CENT SIGN
-                .replaceKeyOfLabel("\u20AC", key("$", moreKey("\u00A2")))
-                // U+00A2: "¢" CENT SIGN
-                // U+00A5: "¥" YEN SIGN
-                .replaceKeyOfLabel("\u00A2", key("\u00A5"));
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractKeyboardBuilder.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractKeyboardBuilder.java
index 45449b7..682ac20 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractKeyboardBuilder.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractKeyboardBuilder.java
@@ -73,6 +73,14 @@
     }
 
     /**
+     * Return the number of rows.
+     * @return the number of rows being constructed.
+     */
+    int getRowCount() {
+        return mRows.length;
+    }
+
+    /**
      * Get the current contents of the specified row.
      * @param row the row number to get the contents.
      * @return the array of elements at row number <code>row</code>.
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
index 61288f0..57f842b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
@@ -52,32 +52,56 @@
     }
 
     // A replacement job to be performed.
-    interface ReplaceJob {
-        // Returns a {@link ExpectedKey} object to replace.
-        ExpectedKey replace(final ExpectedKey oldKey);
+    private interface ReplaceJob {
+        // Returns a {@link ExpectedKey} objects to replace.
+        ExpectedKey[] replacingKeys(final ExpectedKey oldKey);
         // Return true if replacing should be stopped at first occurrence.
         boolean stopAtFirstOccurrence();
     }
 
+    private static ExpectedKey[] replaceKeyAt(final ExpectedKey[] keys, final int columnIndex,
+            final ExpectedKey[] replacingKeys) {
+        // Optimization for replacing a key with another key.
+        if (replacingKeys.length == 1) {
+            keys[columnIndex] = replacingKeys[0];
+            return keys;
+        }
+        final int newLength = keys.length - 1 + replacingKeys.length;
+        // Remove the key at columnIndex.
+        final ExpectedKey[] newKeys = Arrays.copyOf(keys, newLength);
+        System.arraycopy(keys, columnIndex + 1, newKeys, columnIndex + replacingKeys.length,
+                keys.length - 1 - columnIndex);
+        // Insert replacing keys at columnIndex.
+        System.arraycopy(replacingKeys, 0, newKeys, columnIndex, replacingKeys.length);
+        return newKeys;
+
+    }
+
     // Replace key(s) that has the specified visual.
     private void replaceKeyOf(final ExpectedKeyVisual visual, final ReplaceJob job) {
         int replacedCount = 0;
-        final ExpectedKey[][] rows = build();
-        for (int rowIndex = 0; rowIndex < rows.length; rowIndex++) {
-            final ExpectedKey[] keys = rows[rowIndex];
-            for (int columnIndex = 0; columnIndex < keys.length; columnIndex++) {
-                if (keys[columnIndex].getVisual().equalsTo(visual)) {
-                    keys[columnIndex] = job.replace(keys[columnIndex]);
-                    replacedCount++;
-                    if (job.stopAtFirstOccurrence()) {
-                        return;
-                    }
+        final int rowCount = getRowCount();
+        for (int row = 1; row <= rowCount; row++) {
+            ExpectedKey[] keys = getRowAt(row);
+            for (int columnIndex = 0; columnIndex < keys.length; /* nothing */) {
+                final ExpectedKey currentKey = keys[columnIndex];
+                if (!currentKey.getVisual().equalsTo(visual)) {
+                    columnIndex++;
+                    continue;
+                }
+                final ExpectedKey[] replacingKeys = job.replacingKeys(currentKey);
+                keys = replaceKeyAt(keys, columnIndex, replacingKeys);
+                columnIndex += replacingKeys.length;
+                setRowAt(row, keys);
+                replacedCount++;
+                if (job.stopAtFirstOccurrence()) {
+                    return;
                 }
             }
         }
         if (replacedCount == 0) {
             throw new RuntimeException(
-                    "Can't find key that has visual: " + visual + " in\n" + toString(rows));
+                    "Can't find key that has visual: " + visual + " in\n" + this);
         }
     }
 
@@ -137,8 +161,10 @@
     private void setMoreKeysOf(final ExpectedKeyVisual visual, final ExpectedKey[] moreKeys) {
         replaceKeyOf(visual, new ReplaceJob() {
             @Override
-            public ExpectedKey replace(final ExpectedKey oldKey) {
-                return ExpectedKey.newInstance(oldKey.getVisual(), oldKey.getOutput(), moreKeys);
+            public ExpectedKey[] replacingKeys(final ExpectedKey oldKey) {
+                return new ExpectedKey[] {
+                    ExpectedKey.newInstance(oldKey.getVisual(), oldKey.getOutput(), moreKeys)
+                };
             }
             @Override
             public boolean stopAtFirstOccurrence() {
@@ -194,17 +220,18 @@
     }
 
     /**
-     * Replace the most top-left key that has the specified label with the new key.
-     * @param label the label of the key to set <code>newKey</code>.
-     * @param newKey the key to be set.
+     * Replace the most top-left key that has the specified label with the new keys.
+     * @param label the label of the key to set <code>newKeys</code>.
+     * @param newKeys the keys to be set.
      * @return this builder.
      */
-    public ExpectedKeyboardBuilder replaceKeyOfLabel(final String label, final ExpectedKey newKey) {
+    public ExpectedKeyboardBuilder replaceKeyOfLabel(final String label,
+            final ExpectedKey ... newKeys) {
         final ExpectedKeyVisual visual = ExpectedKeyVisual.newInstance(label);
         replaceKeyOf(visual, new ReplaceJob() {
             @Override
-            public ExpectedKey replace(final ExpectedKey oldKey) {
-                return newKey;
+            public ExpectedKey[] replacingKeys(final ExpectedKey oldKey) {
+                return newKeys;
             }
             @Override
             public boolean stopAtFirstOccurrence() {
@@ -215,17 +242,17 @@
     }
 
     /**
-     * Replace the all specified keys  with the new key.
-     * @param key the key to be replaced by <code>newKey</code>.
-     * @param newKey the key to be set.
+     * Replace the all specified keys with the new keys.
+     * @param key the key to be replaced by <code>newKeys</code>.
+     * @param newKeys the keys to be set.
      * @return this builder.
      */
-    public ExpectedKeyboardBuilder replaceKeyOfAll(final ExpectedKey key,
-            final ExpectedKey newKey) {
+    public ExpectedKeyboardBuilder replaceKeysOfAll(final ExpectedKey key,
+            final ExpectedKey ... newKeys) {
         replaceKeyOf(key.getVisual(), new ReplaceJob() {
             @Override
-            public ExpectedKey replace(final ExpectedKey oldKey) {
-                return newKey;
+            public ExpectedKey[] replacingKeys(final ExpectedKey oldKey) {
+                return newKeys;
             }
             @Override
             public boolean stopAtFirstOccurrence() {
@@ -236,22 +263,26 @@
     }
 
     /**
-     * Returns new keyboard instance that has upper case keys of the specified keyboard.
-     * @param rows the lower case keyboard.
+     * Convert all keys of this keyboard builder to upper case keys.
      * @param locale the locale used to convert cases.
-     * @return the upper case keyboard.
+     * @return this builder
      */
-    public static ExpectedKey[][] toUpperCase(final ExpectedKey[][] rows, final Locale locale) {
-        final ExpectedKey[][] upperCaseRows = new ExpectedKey[rows.length][];
-        for (int rowIndex = 0; rowIndex < rows.length; rowIndex++) {
-            final ExpectedKey[] lowerCaseKeys = rows[rowIndex];
+    public ExpectedKeyboardBuilder toUpperCase(final Locale locale) {
+        final int rowCount = getRowCount();
+        for (int row = 1; row <= rowCount; row++) {
+            final ExpectedKey[] lowerCaseKeys = getRowAt(row);
             final ExpectedKey[] upperCaseKeys = new ExpectedKey[lowerCaseKeys.length];
             for (int columnIndex = 0; columnIndex < lowerCaseKeys.length; columnIndex++) {
                 upperCaseKeys[columnIndex] = lowerCaseKeys[columnIndex].toUpperCase(locale);
             }
-            upperCaseRows[rowIndex] = upperCaseKeys;
+            setRowAt(row, upperCaseKeys);
         }
-        return upperCaseRows;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return toString(build());
     }
 
     /**
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java
index 1aeb8c0..1d242d0 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java
@@ -18,6 +18,10 @@
 
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Base class to create an expected keyboard for unit test.
@@ -71,6 +75,24 @@
         return ExpectedKey.newInstance(label, code);
     }
 
+    // Helper method to create {@link ExpectedKey} array by joining {@link ExpectedKey},
+    // {@link ExpectedKey} array, and {@link String}.
+    public static ExpectedKey[] join(final Object ... keys) {
+        final ArrayList<ExpectedKey> list = CollectionUtils.newArrayList();
+        for (final Object key : keys) {
+            if (key instanceof ExpectedKey) {
+                list.add((ExpectedKey)key);
+            } else if (key instanceof ExpectedKey[]) {
+                list.addAll(Arrays.asList((ExpectedKey[])key));
+            } else if (key instanceof String) {
+                list.add(key((String)key));
+            } else {
+                throw new RuntimeException("Unknown expected key type: " + key);
+            }
+        }
+        return list.toArray(new ExpectedKey[list.size()]);
+    }
+
     // Icon ids.
     private static final int ICON_SHIFT = KeyboardIconsSet.getIconId("shift_key");
     private static final int ICON_DELETE = KeyboardIconsSet.getIconId("delete_key");
@@ -99,9 +121,11 @@
             "&", "%", "+", "\"", "-", ":", "@"
     };
 
-    private static ExpectedKeyboardBuilder toPhoneAlphabet(final ExpectedKeyboardBuilder builder) {
-        return builder
-                .addKeysOnTheLeftOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY))
+    // Helper method to create alphabet layout for phone by adding special function keys except
+    // shift key.
+    private static ExpectedKeyboardBuilder convertToPhoneAlphabetKeyboardBuilder(
+            final ExpectedKey[][] commonLayout) {
+        return new ExpectedKeyboardBuilder(commonLayout)
                 .addKeysOnTheRightOfRow(3, DELETE_KEY)
                 .setLabelsOfRow(4, ",", " ", ".")
                 .setMoreKeysOf(",", SETTINGS_KEY)
@@ -112,9 +136,9 @@
 
     // Helper method to create alphabet layout for tablet by adding special function keys except
     // shift key.
-    public static ExpectedKeyboardBuilder toTabletAlphabetWithoutShiftKeys(
-            final ExpectedKeyboardBuilder builder) {
-        return builder
+    private static ExpectedKeyboardBuilder convertToTabletAlphabetKeyboardBuilder(
+            final ExpectedKey[][] commonLayout) {
+        return new ExpectedKeyboardBuilder(commonLayout)
                 // U+00BF: "¿" INVERTED QUESTION MARK
                 // U+00A1: "¡" INVERTED EXCLAMATION MARK
                 .addKeysOnTheRightOfRow(3,
@@ -128,13 +152,20 @@
     }
 
     // Helper method to create alphabet layout by adding special function keys.
-    public static ExpectedKey[][] toCommonAlphabet(final ExpectedKey[][] common,
+    public static ExpectedKey[][] getAlphabetLayoutWithoutShiftKeys(
+            final ExpectedKey[][] commonLayout, final boolean isPhone) {
+        return isPhone ? convertToPhoneAlphabetKeyboardBuilder(commonLayout).build()
+                : convertToTabletAlphabetKeyboardBuilder(commonLayout).build();
+    }
+
+    // Helper method to create alphabet layout by adding special function keys.
+    public static ExpectedKey[][] getDefaultAlphabetLayout(final ExpectedKey[][] commonLayout,
             final boolean isPhone) {
-        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(common);
+        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(
+                getAlphabetLayoutWithoutShiftKeys(commonLayout, isPhone));
         if (isPhone) {
-            toPhoneAlphabet(builder);
+            builder.addKeysOnTheLeftOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY));
         } else {
-            toTabletAlphabetWithoutShiftKeys(builder);
             builder.addKeysOnTheLeftOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY))
                     .addKeysOnTheRightOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY));
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
index 427e7de..5c51d08 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
@@ -68,6 +68,11 @@
         return LayoutBase.key(label, outputText, moreKeys);
     }
 
+    // Helper method to create {@link ExpectedKey} object that has new "more keys".
+    static ExpectedKey key(final ExpectedKey key, final ExpectedKey ... moreKeys) {
+        return LayoutBase.key(key, moreKeys);
+    }
+
     // Helper method to create {@link ExpectedKey} object for "more key" that has the label.
     static ExpectedKey moreKey(final String label) {
         return LayoutBase.moreKey(label);
@@ -79,6 +84,12 @@
         return LayoutBase.moreKey(label, outputText);
     }
 
+    // Helper method to create {@link ExpectedKey} array by joining {@link ExpectedKey},
+    // {@link ExpectedKey} array, and {@link String}.
+    static ExpectedKey[] join(final Object ... keys) {
+        return LayoutBase.join(keys);
+    }
+
     // Locale for testing subtype.
     abstract Locale getTestLocale();
 
@@ -86,73 +97,73 @@
     abstract String getTestKeyboardLayout();
 
     // Alphabet keyboard for testing subtype.
-    abstract ExpectedKey[][] getAlphabet(final boolean isPhone);
+    abstract ExpectedKey[][] getAlphabetLayout(final boolean isPhone);
 
     // Alphabet automatic shifted keyboard for testing subtype.
-    ExpectedKey[][] getAlphabetAutomaticShifted(final boolean isPhone) {
-        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    ExpectedKey[][] getAlphabetAutomaticShiftedLayout(final boolean isPhone) {
+        return AlphabetShifted.getDefaultLayout(getAlphabetLayout(isPhone), getTestLocale());
     }
 
     // Alphabet manual shifted  keyboard for testing subtype.
-    ExpectedKey[][] getAlphabetManualShifted(final boolean isPhone) {
-        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    ExpectedKey[][] getAlphabetManualShiftedLayout(final boolean isPhone) {
+        return AlphabetShifted.getDefaultLayout(getAlphabetLayout(isPhone), getTestLocale());
     }
 
     // Alphabet shift locked keyboard for testing subtype.
-    ExpectedKey[][] getAlphabetShiftLocked(final boolean isPhone) {
-        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    ExpectedKey[][] getAlphabetShiftLockedLayout(final boolean isPhone) {
+        return AlphabetShifted.getDefaultLayout(getAlphabetLayout(isPhone), getTestLocale());
     }
 
     // Alphabet shift lock shifted keyboard for testing subtype.
-    ExpectedKey[][] getAlphabetShiftLockShifted(final boolean isPhone) {
-        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    ExpectedKey[][] getAlphabetShiftLockShiftedLayout(final boolean isPhone) {
+        return AlphabetShifted.getDefaultLayout(getAlphabetLayout(isPhone), getTestLocale());
     }
 
     // Symbols keyboard for testing subtype.
-    ExpectedKey[][] getSymbols(final boolean isPhone) {
-        return Symbols.getSymbols(isPhone);
+    ExpectedKey[][] getSymbolsLayout(final boolean isPhone) {
+        return Symbols.getDefaultLayout(isPhone);
     }
 
     // Symbols shifted keyboard for testing subtype.
-    ExpectedKey[][] getSymbolsShifted(final boolean isPhone) {
-        return SymbolsShifted.getSymbolsShifted(isPhone);
+    ExpectedKey[][] getSymbolsShiftedLayout(final boolean isPhone) {
+        return SymbolsShifted.getDefaultLayout(isPhone);
     }
 
     // TODO: Add phone, phone symbols, number, number password layout tests.
 
     public final void testAlphabet() {
         final int elementId = KeyboardId.ELEMENT_ALPHABET;
-        doKeyboardTests(elementId, getAlphabet(isPhone()));
+        doKeyboardTests(elementId, getAlphabetLayout(isPhone()));
     }
 
     public final void testAlphabetAutomaticShifted() {
         final int elementId = KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED;
-        doKeyboardTests(elementId, getAlphabetAutomaticShifted(isPhone()));
+        doKeyboardTests(elementId, getAlphabetAutomaticShiftedLayout(isPhone()));
     }
 
     public final void testAlphabetManualShifted() {
         final int elementId = KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED;
-        doKeyboardTests(elementId, getAlphabetManualShifted(isPhone()));
+        doKeyboardTests(elementId, getAlphabetManualShiftedLayout(isPhone()));
     }
 
     public final void testAlphabetShiftLocked() {
         final int elementId = KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED;
-        doKeyboardTests(elementId, getAlphabetShiftLocked(isPhone()));
+        doKeyboardTests(elementId, getAlphabetShiftLockedLayout(isPhone()));
     }
 
     public final void testAlphabetShiftLockShifted() {
         final int elementId = KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED;
-        doKeyboardTests(elementId, getAlphabetShiftLockShifted(isPhone()));
+        doKeyboardTests(elementId, getAlphabetShiftLockShiftedLayout(isPhone()));
     }
 
     public final void testSymbols() {
         final int elementId = KeyboardId.ELEMENT_SYMBOLS;
-        doKeyboardTests(elementId, getSymbols(isPhone()));
+        doKeyboardTests(elementId, getSymbolsLayout(isPhone()));
     }
 
     public final void testSymbolsShifted() {
         final int elementId = KeyboardId.ELEMENT_SYMBOLS_SHIFTED;
-        doKeyboardTests(elementId, getSymbolsShifted(isPhone()));
+        doKeyboardTests(elementId, getSymbolsShiftedLayout(isPhone()));
     }
 
     // Comparing expected keyboard and actual keyboard.
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
index 0792a57..fd1a606 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
@@ -36,12 +36,12 @@
 
     @Override
     String getTestKeyboardLayout() {
-        return "qwerty";
+        return Qwerty.LAYOUT_NAME;
     }
 
     @Override
-    ExpectedKey[][] getAlphabet(final boolean isPhone) {
-        final ExpectedKey[][] keyboard = Qwerty.getAlphabet(isPhone);
+    ExpectedKey[][] getAlphabetLayout(final boolean isPhone) {
+        final ExpectedKey[][] keyboard = Qwerty.getLayout(isPhone);
         final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(keyboard);
         setAccentedLetters(builder);
         return builder.build();
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index d9c35c4..4d44135 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -948,10 +948,13 @@
             final HashSet<String> bigramWord1s = bigrams.get(word0);
             final WordProperty wordProperty = binaryDictionary.getWordProperty(word0);
             assertEquals(bigramWord1s.size(), wordProperty.mBigrams.size());
+            final int unigramProbability = wordProperty.getProbability();
             for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
                 final String word1 = wordProperty.mBigrams.get(j).mWord;
                 assertTrue(bigramWord1s.contains(word1));
-                final int probability = wordProperty.mBigrams.get(j).getProbability();
+                final int bigramProbability = wordProperty.mBigrams.get(j).getProbability();
+                final int probability = binaryDictionary.calculateProbability(
+                        unigramProbability, bigramProbability);
                 assertEquals((int)bigramProbabilities.get(new Pair<String, String>(word0, word1)),
                         probability);
                 assertEquals(wordProperty.mBigrams.get(j).getProbability(), probability);
@@ -1037,11 +1040,14 @@
             assertEquals((int)wordProbabilitiesToCheckLater.get(word0),
                     wordProperty.mProbabilityInfo.mProbability);
             wordSet.remove(word0);
+            final int unigramProbability = wordProperty.getProbability();
             final HashSet<String> bigramWord1s = bigrams.get(word0);
             for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
                 final String word1 = wordProperty.mBigrams.get(j).mWord;
                 assertTrue(bigramWord1s.contains(word1));
-                final int probability = wordProperty.mBigrams.get(j).getProbability();
+                final int bigramProbability = wordProperty.mBigrams.get(j).getProbability();
+                final int probability = binaryDictionary.calculateProbability(
+                        unigramProbability, bigramProbability);
                 final Pair<String, String> bigram = new Pair<String, String>(word0, word1);
                 assertEquals((int)bigramProbabilitiesToCheckLater.get(bigram), probability);
                 bigramSet.remove(bigram);
diff --git a/tools/make-keyboard-text/res/values-is/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-is/donottranslate-more-keys.xml
index 4b4d986..2886d01 100644
--- a/tools/make-keyboard-text/res/values-is/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-is/donottranslate-more-keys.xml
@@ -64,12 +64,6 @@
     <string name="more_keys_for_d">&#x00F0;</string>
     <!-- U+00FE: "þ" LATIN SMALL LETTER THORN -->
     <string name="more_keys_for_t">&#x00FE;</string>
-    <!-- U+00F0: "ð" LATIN SMALL LETTER ETH -->
-    <string name="keylabel_for_nordic_row1_11">&#x00F0;</string>
-    <!-- U+00E6: "æ" LATIN SMALL LETTER AE -->
-    <string name="keylabel_for_nordic_row2_10">&#x00E6;</string>
-    <!-- U+00FE: "þ" LATIN SMALL LETTER THORN -->
-    <string name="keylabel_for_nordic_row2_11">&#x00FE;</string>
     <string name="single_quotes">!text/single_9qm_lqm</string>
     <string name="double_quotes">!text/double_9qm_lqm</string>
 </resources>
diff --git a/tools/make-keyboard-text/res/values-lt/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-lt/donottranslate-more-keys.xml
index 7e2b8a0..c1c5960 100644
--- a/tools/make-keyboard-text/res/values-lt/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-lt/donottranslate-more-keys.xml
@@ -71,9 +71,8 @@
     <string name="more_keys_for_s">&#x0161;,&#x00DF;,&#x015B;,&#x015F;</string>
     <!-- U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
          U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-         U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
          U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE -->
-    <string name="more_keys_for_n">&#x0146;,&#x00F1;,&#x0144;,&#x0144;</string>
+    <string name="more_keys_for_n">&#x0146;,&#x00F1;,&#x0144;</string>
     <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON
          U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
          U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE -->
diff --git a/tools/make-keyboard-text/res/values-lv/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-lv/donottranslate-more-keys.xml
index c64e37b..c27458b 100644
--- a/tools/make-keyboard-text/res/values-lv/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-lv/donottranslate-more-keys.xml
@@ -70,9 +70,8 @@
     <string name="more_keys_for_s">&#x0161;,&#x00DF;,&#x015B;,&#x015F;</string>
     <!-- U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
          U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-         U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
          U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE -->
-    <string name="more_keys_for_n">&#x0146;,&#x00F1;,&#x0144;,&#x0144;</string>
+    <string name="more_keys_for_n">&#x0146;,&#x00F1;,&#x0144;</string>
     <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON
          U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
          U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE -->
diff --git a/tools/make-keyboard-text/res/values-sk/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-sk/donottranslate-more-keys.xml
index 2ed538e..cf2238f 100644
--- a/tools/make-keyboard-text/res/values-sk/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-sk/donottranslate-more-keys.xml
@@ -71,9 +71,8 @@
     <!-- U+0148: "ň" LATIN SMALL LETTER N WITH CARON
          U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
          U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-         U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
          U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE -->
-    <string name="more_keys_for_n">&#x0148;,&#x0146;,&#x00F1;,&#x0144;,&#x0144;</string>
+    <string name="more_keys_for_n">&#x0148;,&#x0146;,&#x00F1;,&#x0144;</string>
     <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON
          U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
          U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE -->
diff --git a/tools/make-keyboard-text/res/values-zz/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-zz/donottranslate-more-keys.xml
index eb984a4..ad69019 100644
--- a/tools/make-keyboard-text/res/values-zz/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-zz/donottranslate-more-keys.xml
@@ -29,7 +29,7 @@
          U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
          U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
          U+00AA: "ª" FEMININE ORDINAL INDICATOR -->
-    <string name="more_keys_for_a">&#x00E0;,&#x00E1;,&#x00E2;,&#x00E3;,&#x00E4;,&#x00E5;,&#x00E6;,&#x00E3;,&#x00E5;,&#x0101;,&#x0103;,&#x0105;,&#x00AA;</string>
+    <string name="more_keys_for_a">&#x00E0;,&#x00E1;,&#x00E2;,&#x00E3;,&#x00E4;,&#x00E5;,&#x00E6;,&#x0101;,&#x0103;,&#x0105;,&#x00AA;</string>
     <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
          U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
          U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX