Merge "Import translations. DO NOT MERGE" into jb-ub-latinimegoogle
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
index ad34dc2..fcaeca8 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
@@ -79,4 +79,7 @@
     public static void onWordCommitSuggestionPickedManually(
             final String commitWord, final boolean isBatchMode) {
     }
+
+    public static void onLoadSettings(SettingsValues settingsValues) {
+    }
 }
diff --git a/java/res/values-af/strings-talkback-descriptions.xml b/java/res/values-af/strings-talkback-descriptions.xml
index 3b6ba0a..655760d 100644
--- a/java/res/values-af/strings-talkback-descriptions.xml
+++ b/java/res/values-af/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Hoofletter-I, kol bo"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Onbekende simbool"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Onbekende emosiekoon"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatiewe karakters is beskikbaar"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatiewe karakters is toegemaak"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatiewe voorstelle is beskikbaar"</string>
diff --git a/java/res/values-am/strings-talkback-descriptions.xml b/java/res/values-am/strings-talkback-descriptions.xml
index 84c3cb0..d916d51 100644
--- a/java/res/values-am/strings-talkback-descriptions.xml
+++ b/java/res/values-am/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"አቢይ ሆሄ አይ፣ ነጥብ ከላይ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"ያልታወቀ ምልክት"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"ያልታወቀ ስሜት ገላጭ ምስል"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"የደበረው ፊት"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"ያፈረ ፊት"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"የጸሐይ መነጽር የሚለብስ ፊት"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"የደነቀው ፊት"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"የሚስም ፊት"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"የሚኮሳተር ፊት"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"ተለዋጭ ቁምፊዎች ይገኛሉ"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ተለዋጭ ቁምፊዎች ተሰናብተዋል"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ተለዋጭ የአስተያየት ጥቆማዎች ይገኛሉ"</string>
diff --git a/java/res/values-ar/strings-talkback-descriptions.xml b/java/res/values-ar/strings-talkback-descriptions.xml
index bd2d7c6..7051a73 100644
--- a/java/res/values-ar/strings-talkback-descriptions.xml
+++ b/java/res/values-ar/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"رمز غير معروف"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"رمز تعبيري غير معروف"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"وجه يبدو عليه الملل"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"وجه يبدو عليه الإحراج"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"وجه يرتدي نظارات شمسية"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"وجه يبدو عليه الاندهاش"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"وجه يبعث قبلة"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"وجه عبوس"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"تتوفر الأحرف البديلة"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"تم تجاهل الأحرف البديلة"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"تتوفر الاقتراحات البديلة"</string>
diff --git a/java/res/values-az-rAZ/strings-talkback-descriptions.xml b/java/res/values-az-rAZ/strings-talkback-descriptions.xml
index 8f23627..385a954 100644
--- a/java/res/values-az-rAZ/strings-talkback-descriptions.xml
+++ b/java/res/values-az-rAZ/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Böyük I, üstü nöqtəli"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Naməlum rəmz"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Naməlum emoji"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternativ simvollar əlçatandır"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativ simvollar kənarlaşdırılıb"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternativ təkliflər əlçatandır"</string>
diff --git a/java/res/values-bg/strings-talkback-descriptions.xml b/java/res/values-bg/strings-talkback-descriptions.xml
index c1271bf..e206d1b 100644
--- a/java/res/values-bg/strings-talkback-descriptions.xml
+++ b/java/res/values-bg/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Главна буква I с точка отгоре"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Неизвестен символ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Неизвестен емотикон"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Отегчено лице"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Засрамено лице"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Лице със слънчеви очила"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Изненадано лице"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Целуващо лице"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Намръщено лице"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Налице са алтернативни знаци"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Алтернативните знаци са отхвърлени"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Налице са алтернативни предложения"</string>
diff --git a/java/res/values-ca/strings-talkback-descriptions.xml b/java/res/values-ca/strings-talkback-descriptions.xml
index 9b01c75..bc944d7 100644
--- a/java/res/values-ca/strings-talkback-descriptions.xml
+++ b/java/res/values-ca/strings-talkback-descriptions.xml
@@ -57,7 +57,7 @@
     <string name="announce_keyboard_mode" msgid="6698257917367823205">"Es mostra el teclat per a <xliff:g id="KEYBOARD_MODE">%s</xliff:g>."</string>
     <string name="keyboard_mode_date" msgid="6597407244976713364">"data"</string>
     <string name="keyboard_mode_date_time" msgid="3642804408726668808">"data i hora"</string>
-    <string name="keyboard_mode_email" msgid="1239682082047693644">"correu electrònic"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"adreça electrònica"</string>
     <string name="keyboard_mode_im" msgid="3812086215529493501">"missatgeria"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"número"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"telèfon"</string>
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I majúscula, punt superior"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbol desconegut"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconegut"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara d\'avorriment"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara de vergonya"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara amb ulleres de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara de sorpresa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara que fa un petó"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara que arrufa el nas"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Hi ha caràcters alternatius disponibles."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Els caràcters alternatius s\'ignoren."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Hi ha suggeriments alternatius disponibles."</string>
diff --git a/java/res/values-cs/strings-talkback-descriptions.xml b/java/res/values-cs/strings-talkback-descriptions.xml
index 6c9c800..d26a691 100644
--- a/java/res/values-cs/strings-talkback-descriptions.xml
+++ b/java/res/values-cs/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Velké I s tečkou nad"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Neznámý znak"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Neznámý smajlík emodži"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternativní znaky jsou k dispozici"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativní znaky jsou ignorovány"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternativní návrhy jsou k dispozici"</string>
diff --git a/java/res/values-da/strings-talkback-descriptions.xml b/java/res/values-da/strings-talkback-descriptions.xml
index 5f54004..b13ad9c 100644
--- a/java/res/values-da/strings-talkback-descriptions.xml
+++ b/java/res/values-da/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Stort I med prik over"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ukendt symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Ukendt emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Træt ansigt"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Forlegent ansigt"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Ansigt med solbriller"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Overrasket ansigt"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kyssende ansigt"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Surt ansigt"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative tegn er tilgængelige"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative tegn er deaktiveret"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative forslag er tilgængelige"</string>
diff --git a/java/res/values-de/strings-talkback-descriptions.xml b/java/res/values-de/strings-talkback-descriptions.xml
index 27e9ecc..3085afe 100644
--- a/java/res/values-de/strings-talkback-descriptions.xml
+++ b/java/res/values-de/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Großbuchstabe I mit übergesetztem Punkt"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Unbekanntes Symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Unbekanntes Emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Gelangweiltes Gesicht"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Verlegenes Gesicht"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Gesicht mit Sonnenbrille"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Überraschtes Gesicht"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Küssendes Gesicht"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Finsteres Gesicht"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Es sind Alternativzeichen verfügbar."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativzeichen werden ausgeblendet."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Es sind Alternativvorschläge verfügbar."</string>
diff --git a/java/res/values-el/strings-talkback-descriptions.xml b/java/res/values-el/strings-talkback-descriptions.xml
index 10df02f..1300a95 100644
--- a/java/res/values-el/strings-talkback-descriptions.xml
+++ b/java/res/values-el/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Κεφαλαίο I, κουκκίδα από πάνω"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Άγνωστο σύμβολο"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Άγνωστο emoticon"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Πρόσωπο που βαριέται"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Αμήχανο πρόσωπο"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Πρόσωπο που φορά γυαλιά ηλίου"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Έκπληκτο πρόσωπο"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Πρόσωπο που δίνει φιλί"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Συνοφρυωμένο πρόσωπο"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Διατίθενται εναλλακτικοί χαρακτήρες"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Παράβλεψη εναλλακτικών χαρακτήρων"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Διατίθενται εναλλακτικές προτάσεις"</string>
diff --git a/java/res/values-en-rGB/strings-talkback-descriptions.xml b/java/res/values-en-rGB/strings-talkback-descriptions.xml
index e209b54..aa805c9 100644
--- a/java/res/values-en-rGB/strings-talkback-descriptions.xml
+++ b/java/res/values-en-rGB/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Unknown symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Unknown emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Bored face"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarrassed face"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Face wearing sunglasses"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surprised face"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kissing face"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Frowning face"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative characters are available"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative characters are dismissed"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative suggestions are available"</string>
diff --git a/java/res/values-en-rIN/strings-talkback-descriptions.xml b/java/res/values-en-rIN/strings-talkback-descriptions.xml
index e209b54..aa805c9 100644
--- a/java/res/values-en-rIN/strings-talkback-descriptions.xml
+++ b/java/res/values-en-rIN/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Unknown symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Unknown emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Bored face"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarrassed face"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Face wearing sunglasses"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surprised face"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kissing face"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Frowning face"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative characters are available"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative characters are dismissed"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative suggestions are available"</string>
diff --git a/java/res/values-es-rUS/strings-talkback-descriptions.xml b/java/res/values-es-rUS/strings-talkback-descriptions.xml
index 0bde67e..43105e9 100644
--- a/java/res/values-es-rUS/strings-talkback-descriptions.xml
+++ b/java/res/values-es-rUS/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I mayúscula, con punto superior"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconocido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconocido"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Hay caracteres alternativos disponibles."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Los caracteres alternativos se descartan."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Hay sugerencias alternativas disponibles."</string>
diff --git a/java/res/values-es/strings-talkback-descriptions.xml b/java/res/values-es/strings-talkback-descriptions.xml
index ef95901..0a55036 100644
--- a/java/res/values-es/strings-talkback-descriptions.xml
+++ b/java/res/values-es/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maýuscula, punto superior"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconocido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconocido"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara aburrida"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara avergonzada"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara con gafas de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara sorprendida"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara dando un beso"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara con el ceño fruncido"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Caracteres alternativos disponibles"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Los caracteres alternativos se descartarán"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sugerencias alternativas disponibles"</string>
diff --git a/java/res/values-et-rEE/strings-talkback-descriptions.xml b/java/res/values-et-rEE/strings-talkback-descriptions.xml
index b47df1b..9bcd0bb 100644
--- a/java/res/values-et-rEE/strings-talkback-descriptions.xml
+++ b/java/res/values-et-rEE/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Suurtäht I, ülapunkt"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Tundmatu sümbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Tundmatu emoji"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatiivsed tähemärgid on saadaval"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatiivsed tähemärgid eemaldatakse"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatiivsed soovitused on saadaval"</string>
diff --git a/java/res/values-fa/strings-talkback-descriptions.xml b/java/res/values-fa/strings-talkback-descriptions.xml
index 988dd5c..6e4d9fd 100644
--- a/java/res/values-fa/strings-talkback-descriptions.xml
+++ b/java/res/values-fa/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"‏I بزرگ با نقطه بالایی"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"نماد نامشخص"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"‏شکلک emoji نامشخص"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"نویسه‌های جایگزین در دسترس هستند"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"از نویسه‌های جایگزین صرفنظر می‌شود"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"پیشنهادهای جایگزین در دسترس هستند"</string>
diff --git a/java/res/values-fi/strings-talkback-descriptions.xml b/java/res/values-fi/strings-talkback-descriptions.xml
index bec46ca..66ca5fc 100644
--- a/java/res/values-fi/strings-talkback-descriptions.xml
+++ b/java/res/values-fi/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Suuraakkonen I ja yläpuolinen piste"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Tuntematon symboli"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Tuntematon emoji-merkki"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Vaihtoehtoisia merkkejä on saatavilla"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Vaihtoehtoiset merkit hylättiin"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Vaihtoehtoisia ehdotuksia on saatavilla"</string>
diff --git a/java/res/values-fr-rCA/strings-talkback-descriptions.xml b/java/res/values-fr-rCA/strings-talkback-descriptions.xml
index df644c0..84dcae7 100644
--- a/java/res/values-fr-rCA/strings-talkback-descriptions.xml
+++ b/java/res/values-fr-rCA/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I majuscule, point en chef"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Symbole inconnu"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji inconnu"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Ennuyé"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarrassé"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Lunettes de soleil"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surpris"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Bisou"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Sourcils froncés"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Des caractères supplémentaires sont proposés"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Les caractères supplémentaires sont ignorés"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Des suggestions supplémentaires sont proposées"</string>
diff --git a/java/res/values-fr/strings-talkback-descriptions.xml b/java/res/values-fr/strings-talkback-descriptions.xml
index 7ae2056..70c864f 100644
--- a/java/res/values-fr/strings-talkback-descriptions.xml
+++ b/java/res/values-fr/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I majuscule, point en chef"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Symbole inconnu."</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji inconnu."</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Des caractères supplémentaires sont disponibles."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Les caractères supplémentaires sont ignorés."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Des suggestions supplémentaires sont disponibles."</string>
diff --git a/java/res/values-hi/strings-talkback-descriptions.xml b/java/res/values-hi/strings-talkback-descriptions.xml
index aba2592..7a5b2e5 100644
--- a/java/res/values-hi/strings-talkback-descriptions.xml
+++ b/java/res/values-hi/strings-talkback-descriptions.xml
@@ -21,8 +21,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="spoken_use_headphones" msgid="4313642710742229868">"जोर से बोली जाने वाली पासवर्ड कुंजियां सुनने के लिए हैडसेट प्‍लग करें."</string>
-    <string name="spoken_current_text_is" msgid="4240549866156675799">"वर्तमान पाठ %s है"</string>
-    <string name="spoken_no_text_entered" msgid="1711276837961785646">"कोई पाठ नहीं डाला गया"</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"वर्तमान लेख %s है"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"कोई लेख नहीं डाला गया"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> को सुधार कर <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> करता है"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> स्वत: सुधार करता है"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"अज्ञात वर्ण"</string>
@@ -44,7 +44,7 @@
     <string name="spoken_description_search" msgid="5099937658231911288">"खोजें"</string>
     <string name="spoken_description_dot" msgid="5644176501632325560">"डॉट"</string>
     <string name="spoken_description_language_switch" msgid="6818666779313544553">"भाषा स्विच करें"</string>
-    <string name="spoken_description_action_next" msgid="431761808119616962">"अगला"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"आगे"</string>
     <string name="spoken_description_action_previous" msgid="2919072174697865110">"पिछला"</string>
     <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"शिफ़्ट सक्षम किया गया"</string>
     <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"कैप्स लॉक सक्षम किया गया"</string>
@@ -61,7 +61,7 @@
     <string name="keyboard_mode_im" msgid="3812086215529493501">"संदेश सेवा"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"संख्या"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"फ़ोन"</string>
-    <string name="keyboard_mode_text" msgid="9138789594969187494">"पाठ"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"लेख"</string>
     <string name="keyboard_mode_time" msgid="8558297845514402675">"समय"</string>
     <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
     <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"हाल ही के"</string>
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"बड़ा आई, बिंदु ऊपर"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"अज्ञात प्रतीक"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"अज्ञात इमोजी"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"वैकल्पिक वर्ण उपलब्ध हैं"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"वैकल्पिक वर्ण ख़ारिज कर दिए जाते हैं"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"वैकल्पिक सुझाव उपलब्ध हैं"</string>
diff --git a/java/res/values-hr/strings-talkback-descriptions.xml b/java/res/values-hr/strings-talkback-descriptions.xml
index e86db07..b23eed2 100644
--- a/java/res/values-hr/strings-talkback-descriptions.xml
+++ b/java/res/values-hr/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Veliko slovo I, s točkicom iznad"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nepoznati simbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nepoznati emoji"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Dostupni su zamjenski znakovi"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Zamjenski su znakovi isključeni"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Dostupni su zamjenski prijedlozi"</string>
diff --git a/java/res/values-hu/strings-talkback-descriptions.xml b/java/res/values-hu/strings-talkback-descriptions.xml
index ae0c047..554cc97 100644
--- a/java/res/values-hu/strings-talkback-descriptions.xml
+++ b/java/res/values-hu/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Nagy I, felette ponttal"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ismeretlen szimbólum"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Ismeretlen hangulatjel"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Unott arc"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Zavarban lévő arc"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Napszemüveges arc"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Meglepődött arc"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Csókot adó arc"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Homlokráncoló arc"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Az alternatív karakterek elérhetők"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Az alternatív karakterek billentyűzete bezárva"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Az alternatív javaslatok elérhetők"</string>
diff --git a/java/res/values-hy-rAM/strings-talkback-descriptions.xml b/java/res/values-hy-rAM/strings-talkback-descriptions.xml
index 44784bd..ed502a8 100644
--- a/java/res/values-hy-rAM/strings-talkback-descriptions.xml
+++ b/java/res/values-hy-rAM/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Մեծատառ I, վերևում կետիկ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Անհայտ նշան"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Անհայտ զմայլիկ"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Լրացուցիչ տառանշաններով ստեղնաշարը հասանելի է"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Լրացուցիչ տառանշաններով ստեղնաշարը փակված է"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Լրացուցիչ առաջարկներով վահանակը հասանելի է"</string>
diff --git a/java/res/values-in/strings-talkback-descriptions.xml b/java/res/values-in/strings-talkback-descriptions.xml
index f7334d9..ef31573 100644
--- a/java/res/values-in/strings-talkback-descriptions.xml
+++ b/java/res/values-in/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Huruf kapital I dengan aksen titik di bagian atas"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbol tak dikenal"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji tak dikenal"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Wajah bosan"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Wajah malu"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Wajah mengenakan kacamata hitam"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Wajah terkejut"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Wajah mencium"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Wajah merengut"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Karakter alternatif tersedia"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Karakter alternatif ditolak"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Saran alternatif tersedia"</string>
diff --git a/java/res/values-it/strings-talkback-descriptions.xml b/java/res/values-it/strings-talkback-descriptions.xml
index 8665530..54bef08 100644
--- a/java/res/values-it/strings-talkback-descriptions.xml
+++ b/java/res/values-it/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiuscola, punto sovrascritto"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbolo sconosciuto"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji sconosciuta"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Faccina annoiata"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Faccina imbarazzata"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Faccina che indossa occhiali da sole"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Faccina sorpresa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Faccina che dà baci"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Faccina corrucciata"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Sono disponibili caratteri alternativi"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"I caratteri alternativi vengono ignorati"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sono disponibili suggerimenti alternativi"</string>
diff --git a/java/res/values-iw/strings-talkback-descriptions.xml b/java/res/values-iw/strings-talkback-descriptions.xml
index a43b64e..24cc1a6 100644
--- a/java/res/values-iw/strings-talkback-descriptions.xml
+++ b/java/res/values-iw/strings-talkback-descriptions.xml
@@ -57,7 +57,7 @@
     <string name="announce_keyboard_mode" msgid="6698257917367823205">"מציג מקלדת <xliff:g id="KEYBOARD_MODE">%s</xliff:g>"</string>
     <string name="keyboard_mode_date" msgid="6597407244976713364">"תאריך"</string>
     <string name="keyboard_mode_date_time" msgid="3642804408726668808">"תאריך ושעה"</string>
-    <string name="keyboard_mode_email" msgid="1239682082047693644">"דוא\"ל"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"אימייל"</string>
     <string name="keyboard_mode_im" msgid="3812086215529493501">"העברת הודעות"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"מספרים"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"מספרי טלפון"</string>
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"‏I גדולה, נקודה מעל"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"סמל לא מוכר"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"‏Emoji לא מוכר"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"פרצוף משועמם"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"פרצוף נבוך"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"פרצוף עם משקפי שמש"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"פרצוף מופתע"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"פרצוף מנשק"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"פרצוף זועף"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"תווים חלופיים זמינים"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"תווים חלופיים נדחים"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"הצעות חלופיות זמינות"</string>
diff --git a/java/res/values-ja/strings-talkback-descriptions.xml b/java/res/values-ja/strings-talkback-descriptions.xml
index e4f5db5..37ac104 100644
--- a/java/res/values-ja/strings-talkback-descriptions.xml
+++ b/java/res/values-ja/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"大文字I、上点"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"不明な記号"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"不明な絵文字"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"代替文字が利用可能です"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"代替文字が消去されます"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"代替候補が利用可能です"</string>
diff --git a/java/res/values-ka-rGE/strings-talkback-descriptions.xml b/java/res/values-ka-rGE/strings-talkback-descriptions.xml
index 5d23b09..1519211 100644
--- a/java/res/values-ka-rGE/strings-talkback-descriptions.xml
+++ b/java/res/values-ka-rGE/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"უცნობი სიმბოლო"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"უცნობი emoji"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"ალტერნატიული სიმბოლოები ხელმისაწვდომია"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ალტერნატიული სიმბოლოები გამოტოვებულია"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ალტერნატიული შეთავაზებები ხელმისაწვდომია"</string>
diff --git a/java/res/values-km-rKH/strings-talkback-descriptions.xml b/java/res/values-km-rKH/strings-talkback-descriptions.xml
index e5b7860..cdc1f7b 100644
--- a/java/res/values-km-rKH/strings-talkback-descriptions.xml
+++ b/java/res/values-km-rKH/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"សញ្ញា İ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"មិន​ស្គាល់​និមិត្តសញ្ញា"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"មិន​ស្គាល់​សញ្ញា​អារម្មណ៍"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"តួអក្សរ​ជំនួស​អាច​ប្រើ​បាន"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"បាន​បដិសេធ​តួអក្សរ​ជំនួស"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ការ​ស្នើ​ជំនួស​អាច​ប្រើ​បាន"</string>
diff --git a/java/res/values-ko/strings-talkback-descriptions.xml b/java/res/values-ko/strings-talkback-descriptions.xml
index 2a3fe88..70e7afc 100644
--- a/java/res/values-ko/strings-talkback-descriptions.xml
+++ b/java/res/values-ko/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"대문자 아이, 위 닷"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"알 수 없는 기호"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"알 수 없는 그림 이모티콘"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"대체 문자를 사용할 수 있습니다"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"대체 문자를 닫았습니다."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"대체 추천 단어를 사용할 수 있습니다"</string>
diff --git a/java/res/values-lo-rLA/strings-talkback-descriptions.xml b/java/res/values-lo-rLA/strings-talkback-descriptions.xml
index 187b63a..ba19a24 100644
--- a/java/res/values-lo-rLA/strings-talkback-descriptions.xml
+++ b/java/res/values-lo-rLA/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"​ໂຕພິມ​ໃຫຍ່ I ມີ​ຈ້ຳ​ເມັດ​ຢູ່​ເທິງ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"ສັນ​ຍາ​ລັກ​ທີ່ບໍ່​ຮູ້​ຈັກ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"ອີ​ໂມ​ຈິ​ທີ່ບໍ່​ຮູ້​ຈັກ"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"​ມີ​ໂຕ​ອັກ​ສອນ​ສຳ​ຮອງ​ໃຫ້​ເລືອກ"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"​ປິດ​ໂຕ​ອັກ​ສອນ​ສຳ​ຮອງ​ແລ້ວ"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"​ມີ​ຄຳ​ແນະ​ນຳ​ສຳ​ຮອງ​ໃຫ້​ເລືອກ"</string>
diff --git a/java/res/values-lt/strings-talkback-descriptions.xml b/java/res/values-lt/strings-talkback-descriptions.xml
index 18b09dd..c49a22d 100644
--- a/java/res/values-lt/strings-talkback-descriptions.xml
+++ b/java/res/values-lt/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Didžioji I su tašku viršuje"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nežinomas simbolis"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nežinomas jaustukas"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatyvūs ženklai pasiekiami"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatyvūs simboliai atmetami"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatyvūs pasiūlymai pasiekiami"</string>
diff --git a/java/res/values-lv/strings-talkback-descriptions.xml b/java/res/values-lv/strings-talkback-descriptions.xml
index 2fe7f91..ad5bf94 100644
--- a/java/res/values-lv/strings-talkback-descriptions.xml
+++ b/java/res/values-lv/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Lielais burts “I” ar punktu virs tā"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nezināms simbols"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nezināma emocijzīme"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Ir pieejamas alternatīvas rakstzīmes."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatīvās rakstzīmes netiek rādītas."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Ir pieejami alternatīvi ieteikumi."</string>
diff --git a/java/res/values-mn-rMN/strings-talkback-descriptions.xml b/java/res/values-mn-rMN/strings-talkback-descriptions.xml
index d2c583e..faee8c3 100644
--- a/java/res/values-mn-rMN/strings-talkback-descriptions.xml
+++ b/java/res/values-mn-rMN/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Том I, дээрээ цэгтэй"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Үл мэдэгдэх симбол"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Үл мэдэгдэх эможи"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Бусад тэмдэгтүүд ашиглах боломжтой"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Бусад тэмдэгтүүдийг хаагдсан"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Бусад санал болголтууд ашиглах боломжтой"</string>
diff --git a/java/res/values-ms-rMY/strings-talkback-descriptions.xml b/java/res/values-ms-rMY/strings-talkback-descriptions.xml
index d5ae637..45eb358 100644
--- a/java/res/values-ms-rMY/strings-talkback-descriptions.xml
+++ b/java/res/values-ms-rMY/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I huruf besar, titik di atas"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbol yang tidak diketahui"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji yang tidak dikethui"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Aksara alternatif adalah tersedia"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Aksara alternatif diketepikan"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Cadangan alternatif tersedia"</string>
diff --git a/java/res/values-nb/strings-talkback-descriptions.xml b/java/res/values-nb/strings-talkback-descriptions.xml
index cdb6858..18afaa7 100644
--- a/java/res/values-nb/strings-talkback-descriptions.xml
+++ b/java/res/values-nb/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Stor I med prikk over"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ukjent symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Ukjent emoji"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative tegn er tilgjengelige"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative tegn fjernes"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative forslag er tilgjengelige"</string>
diff --git a/java/res/values-ne-rNP/strings-talkback-descriptions.xml b/java/res/values-ne-rNP/strings-talkback-descriptions.xml
index 2bbd178..5403558 100644
--- a/java/res/values-ne-rNP/strings-talkback-descriptions.xml
+++ b/java/res/values-ne-rNP/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"अज्ञात प्रतीक"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"अज्ञात इमोजी"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"वैकल्पिक वर्णहरू उपलब्ध छन्"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"वैकल्पिक वर्णहरू खारेज गरियो"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"वैकल्पिक सुझावहरू उपलब्ध छन्"</string>
diff --git a/java/res/values-nl/strings-talkback-descriptions.xml b/java/res/values-nl/strings-talkback-descriptions.xml
index c59f3f2..09929f0 100644
--- a/java/res/values-nl/strings-talkback-descriptions.xml
+++ b/java/res/values-nl/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Hoofdletter I, punt erboven"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Onbekend symbool"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Onbekende emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Verveeld gezicht"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Beschaamd gezicht"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Gezicht met zonnebril"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Verbaasd gezicht"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kussend gezicht"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Fronsend gezicht"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatieve tekens zijn beschikbaar"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatieve tekens worden verwijderd"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatieve suggesties zijn beschikbaar"</string>
diff --git a/java/res/values-pl/strings-talkback-descriptions.xml b/java/res/values-pl/strings-talkback-descriptions.xml
index 43fca5f..ac30199 100644
--- a/java/res/values-pl/strings-talkback-descriptions.xml
+++ b/java/res/values-pl/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Wielka litera I z kropką"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nieznany symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nieznany emotikon"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Buźka znudzona"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Buźka zawstydzona"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Buźka w ciemnych okularach"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Buźka zdziwiona"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Buźka całująca"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Buźka marszcząca czoło"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatywne znaki są dostępne"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatywne znaki zostały zamknięte"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatywne propozycje są dostępne"</string>
diff --git a/java/res/values-pt-rPT/strings-talkback-descriptions.xml b/java/res/values-pt-rPT/strings-talkback-descriptions.xml
index 30bbd3f..49a5fdc 100644
--- a/java/res/values-pt-rPT/strings-talkback-descriptions.xml
+++ b/java/res/values-pt-rPT/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiúsculo, ponto sobreposto"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconhecido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconhecido"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara aborrecida"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara envergonhada"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara com óculos de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara surpreendida"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara a dar um beijo"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara franzida"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Os carateres alternativos estão disponíveis"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Os carateres alternativos são ignorados"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"As sugestões alternativas estão disponíveis"</string>
diff --git a/java/res/values-pt/strings-talkback-descriptions.xml b/java/res/values-pt/strings-talkback-descriptions.xml
index f4e28fc..4ed474d 100644
--- a/java/res/values-pt/strings-talkback-descriptions.xml
+++ b/java/res/values-pt/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiúscula, ponto acima"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconhecido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconhecido"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Caracteres alternativos estão disponíveis"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Caracteres alternativos foram descartados"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sugestões alternativas estão disponíveis"</string>
diff --git a/java/res/values-ro/strings-talkback-descriptions.xml b/java/res/values-ro/strings-talkback-descriptions.xml
index 7a90162..fda18fb 100644
--- a/java/res/values-ro/strings-talkback-descriptions.xml
+++ b/java/res/values-ro/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I mare, punct deasupra"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbol necunoscut"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji necunoscut"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Sunt disponibile caractere alternative"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"S-au închis caracterele alternative"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sunt disponibile sugestii alternative"</string>
diff --git a/java/res/values-ru/strings-talkback-descriptions.xml b/java/res/values-ru/strings-talkback-descriptions.xml
index b23d40d..8d58499 100644
--- a/java/res/values-ru/strings-talkback-descriptions.xml
+++ b/java/res/values-ru/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Заглавная латинская I с точкой сверху."</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Неизвестный символ."</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Неизвестный смайлик."</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Доступны дополнительные символы."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Дополнительные символы скрыты."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Доступны дополнительные подсказки."</string>
diff --git a/java/res/values-sk/strings-talkback-descriptions.xml b/java/res/values-sk/strings-talkback-descriptions.xml
index 2cd094e..cbeb4fc 100644
--- a/java/res/values-sk/strings-talkback-descriptions.xml
+++ b/java/res/values-sk/strings-talkback-descriptions.xml
@@ -63,7 +63,7 @@
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"telefón"</string>
     <string name="keyboard_mode_text" msgid="9138789594969187494">"text"</string>
     <string name="keyboard_mode_time" msgid="8558297845514402675">"čas"</string>
-    <string name="keyboard_mode_url" msgid="8072011652949962550">"Adresa URL"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"Webová adresa"</string>
     <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"Nedávne"</string>
     <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"Ľudia"</string>
     <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Predmety"</string>
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Veľké I s bodkou nad písmenom"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Neznámy symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Neznámy symbol Emodži"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatívne znaky sú dostupné"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatívne znaky boli zrušené"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatívne návrhy sú dostupné"</string>
diff --git a/java/res/values-sl/strings-talkback-descriptions.xml b/java/res/values-sl/strings-talkback-descriptions.xml
index baef01f..85297b8 100644
--- a/java/res/values-sl/strings-talkback-descriptions.xml
+++ b/java/res/values-sl/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Velika črka I s piko zgoraj"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Neznan simbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Neznan znak »emoji«"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Nadomestni znaki so na voljo"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Nadomestni znaki se ne upoštevajo"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Nadomestni predlogi so na voljo"</string>
diff --git a/java/res/values-sr/strings-talkback-descriptions.xml b/java/res/values-sr/strings-talkback-descriptions.xml
index 974ad3a..0ba7600 100644
--- a/java/res/values-sr/strings-talkback-descriptions.xml
+++ b/java/res/values-sr/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Велико И са тачком изнад"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Непознат симбол"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Непознати емоџи"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Доступни су алтернативни знаци"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Алтернативни знаци су одбачени"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Доступни су алтернативни предлози"</string>
diff --git a/java/res/values-sv/strings-talkback-descriptions.xml b/java/res/values-sv/strings-talkback-descriptions.xml
index e3f7ca1..058dd7e 100644
--- a/java/res/values-sv/strings-talkback-descriptions.xml
+++ b/java/res/values-sv/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Versalt I, punkt ovanför"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Okänd symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Okänd emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Uttråkat ansikte"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Generat ansikte"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Ansikte med solglasögon"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Förvånat ansikte"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kyssande ansikte"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Ansikte med rynkad panna"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternativa tecken är tillgängliga"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativa tecken avvisas"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternativa förslag är tillgängliga"</string>
diff --git a/java/res/values-sw/strings-talkback-descriptions.xml b/java/res/values-sw/strings-talkback-descriptions.xml
index 6f84aa8..324397a 100644
--- a/java/res/values-sw/strings-talkback-descriptions.xml
+++ b/java/res/values-sw/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Herufi I kubwa, alama ya kitone inayowekwa sehemu ya juu ya herufi katika alfabeti za Kilatini na Kivietnamu"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Alama isiyojulikana"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji isiyojulikana"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Herufi mbadala zinapatikana"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Herufi mbadala huondolewa"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Mapendekezo mbadala yanapatikana"</string>
diff --git a/java/res/values-th/strings-talkback-descriptions.xml b/java/res/values-th/strings-talkback-descriptions.xml
index 5d70d71..0f4d3ec 100644
--- a/java/res/values-th/strings-talkback-descriptions.xml
+++ b/java/res/values-th/strings-talkback-descriptions.xml
@@ -31,7 +31,7 @@
     <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Shift"</string>
     <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"สัญลักษณ์"</string>
     <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Shift"</string>
-    <string name="spoken_description_delete" msgid="3878902286264983302">"นำออก"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"ลบ"</string>
     <string name="spoken_description_to_symbol" msgid="8244903740201126590">"สัญลักษณ์"</string>
     <string name="spoken_description_to_alpha" msgid="4081215210530031950">"ตัวอักษร"</string>
     <string name="spoken_description_to_numeric" msgid="4560261331530795682">"หมายเลข"</string>
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I ตัวใหญ่เติมจุดด้านบน"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"สัญลักษณ์ที่ไม่รู้จัก"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"อีโมจิที่ไม่รู้จัก"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"อักขระทางเลือกพร้อมใช้งาน"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ปิดอักขระทางเลือกแล้ว"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ข้อเสนอแนะทางเลือกพร้อมใช้งาน"</string>
diff --git a/java/res/values-tl/strings-talkback-descriptions.xml b/java/res/values-tl/strings-talkback-descriptions.xml
index f601ad4..a67ea51 100644
--- a/java/res/values-tl/strings-talkback-descriptions.xml
+++ b/java/res/values-tl/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, tuldok sa itaas"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Hindi alam na simbolo"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Hindi alam na emoji"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Available ang mga alternatibong character"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Dini-dismiss ang mga alternatibong character"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Available ang mga alternatibong suhestyon"</string>
diff --git a/java/res/values-tr/strings-talkback-descriptions.xml b/java/res/values-tr/strings-talkback-descriptions.xml
index a810eda..a894b18 100644
--- a/java/res/values-tr/strings-talkback-descriptions.xml
+++ b/java/res/values-tr/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Büyük Harf I, üst noktalı"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Bilinmeyen simge"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Bilinmeyen emoji"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatif karakterler kullanılabilir"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatif karakterler yoksayılır"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatif öneriler kullanılabilir"</string>
diff --git a/java/res/values-uk/strings-talkback-descriptions.xml b/java/res/values-uk/strings-talkback-descriptions.xml
index 80e4710..4666e24 100644
--- a/java/res/values-uk/strings-talkback-descriptions.xml
+++ b/java/res/values-uk/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Велика I, крапка вгорі"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Невідомий символ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Невідомий смайл Emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Обличчя, що нудьгує"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Збентежене обличчя"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Обличчя в окулярах"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Здивоване обличчя"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Обличчя, що цілує"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Насуплене обличчя"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Доступні альтернативні символи"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Альтернативні символи відхилено"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Доступні альтернативні пропозиції"</string>
diff --git a/java/res/values-vi/strings-talkback-descriptions.xml b/java/res/values-vi/strings-talkback-descriptions.xml
index 659b1d3..a10f61e 100644
--- a/java/res/values-vi/strings-talkback-descriptions.xml
+++ b/java/res/values-vi/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I hoa, dấu chấm phía trên"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ký hiệu không xác định"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Biểu tượng cảm xúc không xác định"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Có ký tự thay thế"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Ký tự thay thế đã bị loại bỏ"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Có đề xuất thay thế"</string>
diff --git a/java/res/values-zh-rCN/strings-talkback-descriptions.xml b/java/res/values-zh-rCN/strings-talkback-descriptions.xml
index b7b6b41..9213be9 100644
--- a/java/res/values-zh-rCN/strings-talkback-descriptions.xml
+++ b/java/res/values-zh-rCN/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"带上点的拉丁文大写字母I"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"未知符号"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"未知表情符号"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"有可用的替代字符"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"已关闭替代字符"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"有可用的其他建议字词"</string>
diff --git a/java/res/values-zh-rHK/strings-talkback-descriptions.xml b/java/res/values-zh-rHK/strings-talkback-descriptions.xml
index 386b5b5..b6331e9 100644
--- a/java/res/values-zh-rHK/strings-talkback-descriptions.xml
+++ b/java/res/values-zh-rHK/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"上方加點的大寫 I"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"未知的符號"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"未知的表情符號"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"有可用的替代字元"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"已關閉替代字元"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"有可用的建議字詞"</string>
diff --git a/java/res/values-zh-rTW/strings-talkback-descriptions.xml b/java/res/values-zh-rTW/strings-talkback-descriptions.xml
index 7a5f3df..ea220d0 100644
--- a/java/res/values-zh-rTW/strings-talkback-descriptions.xml
+++ b/java/res/values-zh-rTW/strings-talkback-descriptions.xml
@@ -76,6 +76,18 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"上方加點的大寫 I"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"未知的符號"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"未知的表情符號"</string>
+    <!-- no translation found for spoken_emoticon_3A_2D_21_20 (2410905667389534573) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_24_20 (2481260475945560438) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_42_2D_29_20 (1063205250387128068) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_4F_20 (532695091593447238) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_2A_20 (5612342617244114291) -->
+    <skip />
+    <!-- no translation found for spoken_emoticon_3A_2D_5B_20 (2223507987759905920) -->
+    <skip />
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"有可用的替代字元"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"已關閉替代字元"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"有可用的建議字詞"</string>
diff --git a/java/res/values-zu/strings-talkback-descriptions.xml b/java/res/values-zu/strings-talkback-descriptions.xml
index 6d3de70..3e73621 100644
--- a/java/res/values-zu/strings-talkback-descriptions.xml
+++ b/java/res/values-zu/strings-talkback-descriptions.xml
@@ -76,6 +76,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Ufeleba I, icashazi ngenhla"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Uphawu olungaziwa"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"I-emoji engaziwa"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Ubuso obunesithukuthezi"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Ubuso obuphoxekile"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Ubuso obugqoke izibuko"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Ubuso obumangele"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Ukubso bokuqabula"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Ubuso obuswacile"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Ezinye izinhlamvu ziyatholakala"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Ezinye izinhlamvu ziyalahlwa"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Ezinye iziphakamiso ziyatholakala"</string>
diff --git a/java/res/xml-sw600dp/key_period.xml b/java/res/xml-sw600dp/key_period.xml
index df1daf7..3045cbc 100644
--- a/java/res/xml-sw600dp/key_period.xml
+++ b/java/res/xml-sw600dp/key_period.xml
@@ -25,17 +25,6 @@
     <!-- Kept as a separate file for cleaner overriding by an overlay.  -->
     <switch>
         <case
-            latin:languageCode="hi"
-            latin:keyboardLayoutSet="hindi_compact"
-        >
-            <!-- U+0964: "।" DEVANAGARI DANDA -->
-            <Key
-                latin:keySpec="\u0964"
-                latin:keyLabelFlags="hasPopupHint"
-                latin:moreKeys="!autoColumnOrder!8,\\,,.,',#,),(,/,;,@,:,-,&quot;,+,\\%,&amp;"
-                latin:backgroundType="functional" />
-        </case>
-        <case
             latin:keyboardLayoutSet="dvorak"
         >
             <Key
diff --git a/java/res/xml-sw600dp/rows_bengali_akkhor.xml b/java/res/xml-sw600dp/rows_bengali_akkhor.xml
new file mode 100644
index 0000000..3e81a14
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_bengali_akkhor.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor1" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor2" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.182%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.0%p" />
+
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor3" />
+        <include latin:keyboardLayout="@xml/keys_exclamation_question" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_uzbek.xml b/java/res/xml-sw600dp/rows_uzbek.xml
new file mode 100644
index 0000000..3cd9940
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_uzbek.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek1" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek2" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row latin:keyWidth="8.182%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.0%p" />
+        <Spacer latin:keyWidth="3.181%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+        <include latin:keyboardLayout="@xml/keys_exclamation_question" />
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="fillRight"
+            latin:keyXPos="-10.0%p" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/kbd_bengali_akkhor.xml b/java/res/xml/kbd_bengali_akkhor.xml
new file mode 100644
index 0000000..6c81d53
--- /dev/null
+++ b/java/res/xml/kbd_bengali_akkhor.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rows_bengali_akkhor" />
+</Keyboard>
diff --git a/java/res/xml/kbd_uzbek.xml b/java/res/xml/kbd_uzbek.xml
new file mode 100644
index 0000000..84486a7
--- /dev/null
+++ b/java/res/xml/kbd_uzbek.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rows_uzbek" />
+</Keyboard>
\ No newline at end of file
diff --git a/java/res/xml/key_period.xml b/java/res/xml/key_period.xml
index fc27c02..10325ef 100644
--- a/java/res/xml/key_period.xml
+++ b/java/res/xml/key_period.xml
@@ -23,17 +23,6 @@
 >
     <switch>
         <case
-            latin:languageCode="hi"
-            latin:keyboardLayoutSet="hindi_compact"
-        >
-            <!-- U+0964: "।" DEVANAGARI DANDA -->
-            <Key
-                latin:keySpec="\u0964"
-                latin:keyLabelFlags="hasPopupHint"
-                latin:moreKeys="!autoColumnOrder!9,\\,,.,?,!,#,),(,/,;,',@,:,-,&quot;,+,\\%,&amp;"
-                latin:backgroundType="functional" />
-        </case>
-        <case
             latin:languageCode="ne"
             latin:keyboardLayoutSet="nepali_traditional"
         >
diff --git a/java/res/xml/key_styles_currency.xml b/java/res/xml/key_styles_currency.xml
index 2ce6318..de5e6f2 100644
--- a/java/res/xml/key_styles_currency.xml
+++ b/java/res/xml/key_styles_currency.xml
@@ -98,8 +98,9 @@
             <include latin:keyboardLayout="@xml/key_styles_currency_generic" />
         </case>
         <!-- si_LK: Sinhala (Sri Lanka) (Sri Lanka Rupee)
-             ta_LK: Tamil (Sri Lanka) (Sri Lanka Rupee) -->
-        <case latin:countryCode="LK">
+             ta_LK: Tamil (Sri Lanka) (Sri Lanka Rupee)
+             bn_BD: Bengali (Bangladesh) (Taka) -->
+        <case latin:countryCode="LK|BD">
             <include latin:keyboardLayout="@xml/key_styles_currency_generic" />
         </case>
         <!-- bn_IN: Bengali (India) (Indian Rupee)
diff --git a/java/res/xml/keyboard_layout_set_bengali_akkhor.xml b/java/res/xml/keyboard_layout_set_bengali_akkhor.xml
new file mode 100644
index 0000000..b2b09b2
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_bengali_akkhor.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <Feature latin:supportedScript="devanagari" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabet"
+        latin:enableProximityCharsCorrection="true" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetAutomaticShifted"
+        latin:enableProximityCharsCorrection="true" />
+    <!-- On these shifted alphabet layouts the proximity characters correction should be disabled
+         because the letters on these layouts aren't the ones in different case of the above
+         unshifted layouts.-->
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetManualShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetShiftLocked" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetShiftLockShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols"
+        latin:elementName="symbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols_shift"
+        latin:elementName="symbolsShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone"
+        latin:elementName="phone" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone_symbols"
+        latin:elementName="phoneSymbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_number"
+        latin:elementName="number" />
+</KeyboardLayoutSet>
diff --git a/java/res/xml/keyboard_layout_set_uzbek.xml b/java/res/xml/keyboard_layout_set_uzbek.xml
new file mode 100644
index 0000000..8251b01
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_uzbek.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <Element
+        latin:elementName="alphabet"
+        latin:elementKeyboard="@xml/kbd_uzbek"
+        latin:enableProximityCharsCorrection="true"
+        latin:allowRedundantMoreKeys="true" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols"
+        latin:elementName="symbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols_shift"
+        latin:elementName="symbolsShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone"
+        latin:elementName="phone" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone_symbols"
+        latin:elementName="phoneSymbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_number"
+        latin:elementName="number" />
+</KeyboardLayoutSet>
\ No newline at end of file
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 270f90c..8cc6642 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -28,6 +28,7 @@
     be_BY: Belarusian (Belarus)/east_slavic
     bg: Bulgarian/bulgarian
     bg: Bulgarian/bulgarian_bds
+    (bn_BD: Bengali (Bangladesh)/bengali_akkhor) # This is a preliminary keyboard layout.
     bn_IN: Bengali (India)/bengali
     ca: Catalan/spanish
     cs: Czech/qwertz
@@ -100,6 +101,7 @@
     tl: Tagalog/spanish
     tr: Turkish/qwerty
     uk: Ukrainian/east_slavic
+    (uz_UZ: Uzbek (Uzbekistan)/uzbek) # This is a preliminary keyboard layout.
     vi: Vietnamese/qwerty
     zu: Zulu/qwerty
     zz: QWERTY/qwerty
@@ -179,6 +181,16 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian_bds,EmojiCapable"
             android:isAsciiCapable="false"
     />
+    <!-- TODO: This Bengali (Bangladesh) keyboard is a preliminary layout.
+               This isn't based on the final specification. -->
+    <subtype android:icon="@drawable/ic_ime_switcher_dark"
+            android:label="@string/subtype_generic"
+            android:subtypeId="0xa2144b0c"
+            android:imeSubtypeLocale="bn_BD"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="KeyboardLayoutSet=bengali_akkhor,EmojiCapable"
+            android:isAsciiCapable="false"
+    />
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0xbff5986c"
@@ -627,7 +639,6 @@
     />
     <!-- TODO: This Sinhala keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x5c6b3bde"
@@ -636,7 +647,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=sinhala,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x8e94d413"
@@ -661,6 +671,8 @@
             android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable"
             android:isAsciiCapable="false"
     />
+    <!-- TODO: This Serbian Latin keyboard is a preliminary layout.
+               This isn't based on the final specification. -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_sr_ZZ"
             android:subtypeId="0xf4a5569c"
@@ -693,8 +705,7 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=tamil,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    <!-- TODO: Enable ta_LK subtype when si_LK subtype is ready -->
-    <!--
+    <!-- TODO: Enabling/Disabling ta_LK subtype must be aligned with si_LK subtype. -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x6ca12d84"
@@ -703,7 +714,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=tamil,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x785abbd9"
@@ -752,6 +762,16 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable"
             android:isAsciiCapable="false"
     />
+    <!-- TODO: This Uzbek keyboard is a preliminary layout.
+               This isn't based on the final specification. -->
+    <subtype android:icon="@drawable/ic_ime_switcher_dark"
+            android:label="@string/subtype_generic"
+            android:subtypeId="0xad5cf7f6"
+            android:imeSubtypeLocale="uz_UZ"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="KeyboardLayoutSet=uzbek,AsciiCapable,EmojiCapable"
+            android:isAsciiCapable="true"
+    />
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x93972eee"
diff --git a/java/res/xml/rowkeys_bengali_akkhor1.xml b/java/res/xml/rowkeys_bengali_akkhor1.xml
new file mode 100644
index 0000000..bc612be
--- /dev/null
+++ b/java/res/xml/rowkeys_bengali_akkhor1.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+    <switch>
+        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
+            <!-- U+09A2: "ঢ" BENGALI LETTER DDHA -->
+            <Key latin:keySpec="&#x09A2;" />
+            <!-- U+09A0: "ঠ" BENGALI LETTER TTHA -->
+            <Key latin:keySpec="&#x09A0;" />
+            <!-- U+09C8: "ৈ" BENGALI VOWEL SIGN AI
+                 U+0990: "ঐ" BENGALI LETTER AI -->
+            <Key
+                latin:keySpec="&#x09C8;"
+                latin:moreKeys="&#x0990;" />
+            <!-- U+09DC: "ড়" BENGALI LETTER RRA
+                 U+09BC: "়" BENGALI SIGN NUKTA -->
+            <Key
+                latin:keySpec="&#x09DC;"
+                latin:moreKeys="&#x09BC;" />
+            <!-- U+099F: "ট" BENGALI LETTER TTA
+                 U+09F3: "৳" BENGALI RUPEE SIGN
+                 U+099F/U+09CD/U+099F: "ট্ট" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+099F/U+09CD/U+09AC: "ট্ব" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+099F/U+09CD/U+09AE: "ট্ম" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER MA -->
+            <Key
+                latin:keySpec="&#x099F;"
+                latin:moreKeys="&#x09F3;,&#x099F;&#x09CD;&#x099F;,&#x099F;&#x09CD;&#x09AC;,&#x099F;&#x09CD;&#x09AE;" />
+            <!-- U+099E: "ঞ" BENGALI LETTER NYA
+                 U+099E/U+09CD/U+099A: "ঞ্চ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                 U+099E/U+09CD/U+099B: "ঞ্ছ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                 U+099E/U+09CD/U+099C: "ঞ্জ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER JA -->
+            <Key
+                latin:keySpec="&#x099E;"
+                latin:moreKeys="&#x099E;&#x09CD;&#x099A;,&#x099E;&#x09CD;&#x099B;,&#x099E;&#x09CD;&#x099C;" />
+            <!-- U+09C2: "ূ" BENGALI VOWEL SIGN UU
+                 U+098A: "ঊ" BENGALI LETTER UU -->
+            <Key
+                latin:keySpec="&#x09C2;"
+                latin:moreKeys="&#x098A;" />
+            <!-- U+09C0: "ী" BENGALI VOWEL SIGN II
+                 U+0988: "ঈ" BENGALI LETTER II -->
+            <Key
+                latin:keySpec="&#x09C0;"
+                latin:moreKeys="&#x0988;" />
+            <!-- U+09CC: "ৌ" BENGALI VOWEL SIGN AU
+                 U+099A: "ঔ" BENGALI LETTER CA
+                 U+09D7: "ৗ" BENGALI AU LENGTH MARK -->
+            <Key
+                latin:keySpec="&#x09CC;"
+                latin:moreKeys="&#x099A;,&#x09D7;" />
+            <!-- U+09AB: "ফ" BENGALI LETTER PHA
+                 U+09AB/U+09CD/U+099F: "ফ্ট" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09AB/U+09CD/U+09AF: "ফ্য" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09AB/U+09CD/U+09B0: "ফ্র" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AB/U+09CD/U+09B2: "ফ্ল" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09AB;"
+                latin:moreKeys="&#x09AB;&#x09CD;&#x099F;,&#x09AB;&#x09CD;&#x09AF;,&#x09AB;&#x09CD;&#x09B0;,&#x09AB;&#x09CD;&#x09B2;" />
+            <!-- U+098B: "ঋ" BENGALI LETTER VOCALIC R
+                 U+098C: "ঌ" BENGALI LETTER VOCALIC L
+                 U+09E1: "ৡ" BENGALI LETTER VOCALIC LL
+                 U+09F4: "৴" BENGALI CURRENCY NUMERATOR ONE
+                 U+09F5: "৵" BENGALI CURRENCY NUMERATOR TWO
+                 U+09F6: "৶" BENGALI CURRENCY NUMERATOR THREE
+                 U+09E2: " ৢ" BENGALI VOWEL SIGN VOCALIC L
+                 U+09E3: " ৣ" BENGALI VOWEL SIGN VOCALIC LL -->
+            <Key
+                latin:keySpec="&#x098B;"
+                latin:moreKeys="&#x098C;,&#x09E1;,&#x09F4;,&#x09F5;,&#x09F6;,&#x09E2;,&#x09E3;" />
+        </case>
+        <default>
+            <!-- U+09A7: "ধ" BENGALI LETTER DHA
+                 U+09E7: "১" BENGALI DIGIT ONE
+                 U+09A7/U+09CD/U+09AC: "ধ্ব্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A7/U+09CD/U+09AF: "ধ্য্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09A7/U+09CD/U+09B0: "ধ্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x09A7;"
+                latin:keyHintLabel="&#x09E7;"
+                latin:additionalMoreKeys="&#x09E7;"
+                latin:moreKeys="&#x09A7;&#x09CD;&#x09AC;,&#x09A7;&#x09CD;&#x09AF;,&#x09A7;&#x09CD;&#x09B0;" />
+            <!-- U+09A5: "থ" BENGALI LETTER THA
+                 U+09E8: "২" BENGALI DIGIT TWO
+                 U+09A5/U+09CD/U+09AF: "থ্য" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09A5/U+09CD/U+09B0: "থ্র" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x09A5;"
+                latin:keyHintLabel="&#x09E8;"
+                latin:additionalMoreKeys="&#x09E8;"
+                latin:moreKeys="&#x09A5;&#x09CD;&#x09AF;,&#x09A5;&#x09CD;&#x09B0;" />
+            <!-- U+09C7: "ে" BENGALI VOWEL SIGN E
+                 U+09E9: "৩" BENGALI DIGIT THREE
+                 U+098F: "এ" BENGALI LETTER E -->
+            <Key
+                latin:keySpec="&#x09C7;"
+                latin:keyHintLabel="&#x09E9;"
+                latin:additionalMoreKeys="&#x09E9;"
+                latin:moreKeys="&#x098F;" />
+            <!-- U+09B0: "র" BENGALI LETTER RA
+                 U+09EA: "৪" BENGALI DIGIT FOUR -->
+            <Key
+                latin:keySpec="&#x09B0;"
+                latin:keyHintLabel="&#x09EA;"
+                latin:additionalMoreKeys="&#x09EA;" />
+            <!-- U+09A4: "ত" BENGALI LETTER TA
+                 U+09EB: "৫" BENGALI DIGIT FIVE
+                 U+09CE: "ৎ" BENGALI LETTER KHANDA TA
+                 U+09A4/U+09CD/U+09A4: "ত্ত" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09A4/U+09CD/U+09A8: "ত্ন" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09A4/U+09CD/U+09AC: "ত্ব" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A4/U+09CD/U+09AE: "ত্ম" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER MA -->
+            <Key
+                latin:keySpec="&#x09A4;"
+                latin:keyHintLabel="&#x09EB;"
+                latin:additionalMoreKeys="&#x09EB;"
+                latin:moreKeys="&#x09CE;,&#x09A4;&#x09CD;&#x09A4;,&#x09A4;&#x09CD;&#x09A8;,&#x09A4;&#x09CD;&#x09AC;,&#x09A4;&#x09CD;&#x09AE;" />
+            <!-- U+09DF: "য়" BENGALI LETTER YYA
+                 U+09EC: "৬" BENGALI DIGIT SIX -->
+            <Key
+                latin:keySpec="&#x09DF;"
+                latin:keyHintLabel="&#x09EC;"
+                latin:additionalMoreKeys="&#x09EC;" />
+            <!-- U+09C1: "ু" BENGALI VOWEL SIGN U
+                 U+09ED: "৭" BENGALI DIGIT SEVEN
+                 U+0989: "উ" BENGALI LETTER U -->
+            <Key
+                latin:keySpec="&#x09C1;"
+                latin:keyHintLabel="&#x09ED;"
+                latin:additionalMoreKeys="&#x09ED;"
+                latin:moreKeys="&#x0989;" />
+            <!-- U+09BF: "ি" BENGALI VOWEL SIGN I
+                 U+09EE: "৮" BENGALI DIGIT EIGHT
+                 U+0987: "ই BENGALI LETTER I -->
+            <Key
+                latin:keySpec="&#x09BF;"
+                latin:keyHintLabel="&#x09EE;"
+                latin:additionalMoreKeys="&#x09EE;"
+                latin:moreKeys="&#x0987;" />
+            <!-- U+09CB: "ো" BENGALI VOWEL SIGN O
+                 U+09EF: "৯" BENGALI DIGIT NINE
+                 U+0993: "ও" BENGALI LETTER O -->
+            <Key
+                latin:keySpec="&#x09CB;"
+                latin:keyHintLabel="&#x09EF;"
+                latin:additionalMoreKeys="&#x09EF;"
+                latin:moreKeys="&#x0993;" />
+            <!-- U+09AA: "প" BENGALI LETTER PA
+                 U+09E6: "০" BENGALI DIGIT ZERO
+                 U+09AA/U+09CD/U+09A4: "প্ত" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09AA/U+09CD/U+09A8: "প্ন" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09AA/U+09CD/U+09AA: "প্প" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09AA/U+09CD/U+09AF: "প্য" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09AA/U+09CD/U+09B0: "প্র" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AA/U+09CD/U+09B2: "প্ল" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                 U+09AA/U+09CD/U+09B8: "প্স" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER SA -->
+            <Key
+                latin:keySpec="&#x09AA;"
+                latin:keyHintLabel="&#x09E6;"
+                latin:additionalMoreKeys="&#x09E6;"
+                latin:moreKeys="&#x09AA;&#x09CD;&#x09A4;,&#x09AA;&#x09CD;&#x09A8;,&#x09AA;&#x09CD;&#x09AA;,&#x09AA;&#x09CD;&#x09AF;,&#x09AA;&#x09CD;&#x09B0;,&#x09AA;&#x09CD;&#x09B2;,&#x09AA;&#x09CD;&#x09B8;" />
+            <!-- U+0986: "আ" BENGALI LETTER AA -->
+            <Key latin:keySpec="&#x0986;" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_bengali_akkhor2.xml b/java/res/xml/rowkeys_bengali_akkhor2.xml
new file mode 100644
index 0000000..1dbab55
--- /dev/null
+++ b/java/res/xml/rowkeys_bengali_akkhor2.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+    <switch>
+        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
+            <!-- U+0985: "অ" BENGALI LETTER A -->
+            <Key latin:keySpec="&#x0985;" />
+            <!-- U+09B6: "শ" BENGALI LETTER SHA
+                 U+09B6/U+09CD/U+099A: "শ্চ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                 U+09B6/U+09CD/U+099B: "শ্ছ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                 U+09B6/U+09CD/U+09A4: "শ্ত" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09B6/U+09CD/U+09A8: "শ্ন" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09B6/U+09CD/U+09AC: "শ্ব" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B6/U+09CD/U+09AE: "শ্ম" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09B6/U+09CD/U+09B0: "শ্র" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09B6/U+09CD/U+09B2: "শ্ল" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09B6;"
+                latin:moreKeys="&#x09B6;&#x09CD;&#x099A;,&#x09B6;&#x09CD;&#x099B;,&#x09B6;&#x09CD;&#x09A4;,&#x09B6;&#x09CD;&#x09A8;,&#x09B6;&#x09CD;&#x09AC;,&#x09B6;&#x09CD;&#x09AE;,&#x09B6;&#x09CD;&#x09B0;,&#x09B6;&#x09CD;&#x09B2;" />
+            <!-- U+09A1: "ড" BENGALI LETTER DDA
+                 U+09A1/U+09CD/U+09A1: "ড্ড" BENGALI LETTER DDA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA-->
+            <Key
+                latin:keySpec="&#x09A1;"
+                latin:moreKeys="&#x09A1;&#x09CD;&#x09A1;" />
+            <!-- U+09DD: "ঢ়" BENGALI LETTER RHA -->
+            <Key latin:keySpec="&#x09DD;" />
+            <!-- U+0998: "ঘ" BENGALI LETTER GHA -->
+            <Key latin:keySpec="&#x0998;" />
+            <!-- U+09B9: "হ" BENGALI LETTER HA
+                 U+09BD: "ঽ" BENGALI SIGN AVAGRAHA
+                 U+09B9/U+09CD/U+09A3: "হ্ণ" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                 U+09B9/U+09CD/U+09A8: "হ্ন" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09B9/U+09CD/U+09AC: "হ্ব" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B9/U+09CD/U+09AE: "হ্ম" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09B9/U+09CD/U+09B0: "হ্র" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09B9/U+09CD/U+09B2: "হ্ল" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09B9;"
+                latin:moreKeys="&#x09BD;,&#x09B9;&#x09CD;&#x09A3;,&#x09B9;&#x09CD;&#x09A8;,&#x09B9;&#x09CD;&#x09AC;,&#x09B9;&#x09CD;&#x09AE;,&#x09B9;&#x09CD;&#x09B0;,&#x09B9;&#x09CD;&#x09B2;" />
+            <!-- U+099D: "ঝ" BENGALI LETTER JHA -->
+            <Key latin:keySpec="&#x099D;" />
+            <!-- U+0996: "খ" BENGALI LETTER KHA -->
+            <Key latin:keySpec="&#x0996;" />
+            <!-- U+09CE: "ৎ" BENGALI LETTER KHANDA TA -->
+            <Key latin:keySpec="&#x09CE;" />
+            <!-- U+0988: "ঈ" BENGALI LETTER II -->
+            <Key latin:keySpec="&#x0988;" />
+            <!-- U+098A: "ঊ" BENGALI LETTER UU -->
+            <Key latin:keySpec="&#x098A;" />
+        </case>
+        <default>
+            <!-- U+09BE: "া BENGALI VOWEL SIGN AA
+                 U+0986: "আ" BENGALI LETTER AA -->
+            <Key
+                latin:keySpec="&#x09BE;"
+                latin:moreKeys="&#x0986;" />
+            <!-- U+09B8: "স" BENGALI LETTER SA
+                 U+09B8/U+09CD/U+09AC: "স্ব" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B8/U+09CD/U+09A4: "স্ত" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09B8/U+09CD/U+099F: "স্ট" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09B8/U+09CD/U+0995: "স্ক" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+09B8/U+09CD/U+09AA: "স্প" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER PA -->
+            <Key
+                latin:keySpec="&#x09B8;"
+                latin:moreKeys="&#x09B8;&#x09CD;&#x09AC;,&#x09B8;&#x09CD;&#x09A4;,&#x09B8;&#x09CD;&#x099F;,&#x09B8;&#x09CD;&#x0995;,&#x09B8;&#x09CD;&#x09AA;" />
+            <!-- U+09A6: "দ" BENGALI LETTER DA
+                 U+09A6/U+09CD/U+09A6: "দ্দ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09A6/U+09CD/U+09A7: "দ্ধ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09A6/U+09CD/U+09AC: "দ্ব" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A6/U+09CD/U+09AD: "দ্ভ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                 U+09A6/U+09CD/U+09AE: "দ্ম" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09A6/U+09CD/U+09AF: "দ্য" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09A6/U+09CD/U+09B0: "দ্র" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x09A6;"
+                latin:moreKeys="&#x09A6;&#x09CD;&#x09A6;,&#x09A6;&#x09CD;&#x09A7;,&#x09A6;&#x09CD;&#x09AC;,&#x09A6;&#x09CD;&#x09AD;,&#x09A6;&#x09CD;&#x09AE;,&#x09A6;&#x09CD;&#x09AF;,&#x09A6;&#x09CD;&#x09B0;" />
+            <!-- U+09C3: "ৃ" BENGALI VOWEL SIGN VOCALIC R
+                 U+098B: "ঋ" BENGALI LETTER VOCALIC R -->
+            <Key
+                latin:keySpec="&#x09C3;"
+                latin:moreKeys="&#x098B;" />
+            <!-- U+0997: "গ" BENGALI LETTER GA
+                 U+0997/U+09CD/U+09A7: "গ্ধ" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+0997/U+09CD/U+09B0: "গ্র" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+0997/U+09CD/U+09B2: "গ্ল" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                 U+0997/U+09CD/U+09A8: "গ্ন" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER NA -->
+            <Key
+                latin:keySpec="&#x0997;"
+                latin:moreKeys="&#x0997;&#x09CD;&#x09A7;,&#x0997;&#x09CD;&#x09B0;,&#x0997;&#x09CD;&#x09B2;,&#x0997;&#x09CD;&#x09A8;" />
+            <!-- U+09CD: "্" BENGALI SIGN VIRAMA -->
+            <Key latin:keySpec="&#x09CD;" />
+            <!-- U+099C: "জ" BENGALI LETTER JA
+                 U+099C/U+09CD/U+099E: "জ্ঞ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER NYA
+                 U+099C/U+09CD/U+099C: "জ্জ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                 U+099C/U+09CD/U+09AF: "জ্ব" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+099C/U+09CD/U+09AC: "জ্য" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+099C/U+09CD/U+09B0: "জ্র" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x099C;"
+                latin:moreKeys="&#x099C;&#x09CD;&#x099E;,&#x099C;&#x09CD;&#x099C;,&#x099C;&#x09CD;&#x09AF;,&#x099C;&#x09CD;&#x09AC;,&#x099C;&#x09CD;&#x09B0;" />
+            <!-- U+0995: "ক" BENGALI LETTER KA
+                 U+0995/U+09CD/U+09B7: "ক্ষ" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SSA
+                 U+0995/U+09CD/U+0995: "ক্ক" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+0995/U+09CD/U+099F: "ক্ট" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+0995/U+09CD/U+09A4: "ক্ত" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+0995/U+09CD/U+09B0: "ক্র" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+0995/U+09CD/U+09B8: "ক্স" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                 U+0995/U+09CD/U+09B2: "ক্ল" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x0995;"
+                latin:moreKeys="&#x0995;&#x09CD;&#x09B7;,&#x0995;&#x09CD;&#x0995;,&#x0995;&#x09CD;&#x099F;,&#x0995;&#x09CD;&#x09A4;,&#x0995;&#x09CD;&#x09B0;,&#x0995;&#x09CD;&#x09B8;,&#x0995;&#x09CD;&#x09B2;" />
+            <!-- U+09B2: "ল" BENGALI LETTER LA
+                 U+09B2/U+09CD/U+0995: "ল্ক" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+09B2/U+09CD/U+0997: "ল্গ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER GA
+                 U+09B2/U+09CD/U+099F: "ল্ট" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09B2/U+09CD/U+09A1: "ল্ড" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                 U+09B2/U+09CD/U+09A4: "ল্ত" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09B2/U+09CD/U+09A6: "ল্দ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09B2/U+09CD/U+09A7: "ল্ধ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09B2/U+09CD/U+09AA: "ল্প" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09B2/U+09CD/U+09AB: "ল্ফ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                 U+09B2/U+09CD/U+09AC: "ল্ব" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B2/U+09CD/U+09AE: "ল্ম" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09B2/U+09CD/U+09B2: "ল্ল" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09B2;"
+                latin:moreKeys="&#x09B2;&#x09CD;&#x0995;,&#x09B2;&#x09CD;&#x0997;,&#x09B2;&#x09CD;&#x099F;,&#x09B2;&#x09CD;&#x09A1;,&#x09B2;&#x09CD;&#x09A4;,&#x09B2;&#x09CD;&#x09A6;,&#x09B2;&#x09CD;&#x09A7;,&#x09B2;&#x09CD;&#x09AA;,&#x09B2;&#x09CD;&#x09AB;,&#x09B2;&#x09CD;&#x09AC;,&#x09B2;&#x09CD;&#x09AE;,&#x09B2;&#x09CD;&#x09B2;" />
+            <!-- U+0987: "ই" BENGALI LETTER I -->
+            <Key latin:keySpec="&#x0987;" />
+            <!-- U+0989: "উ" BENGALI LETTER U -->
+            <Key latin:keySpec="&#x0989;" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_bengali_akkhor3.xml b/java/res/xml/rowkeys_bengali_akkhor3.xml
new file mode 100644
index 0000000..eb9e836
--- /dev/null
+++ b/java/res/xml/rowkeys_bengali_akkhor3.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+    <switch>
+        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
+            <!-- U+0964: "।" DEVANAGARI DANDA
+                 U+0965: "॥" DEVANAGARI DOUBLE DANDA -->
+            <Key
+                 latin:keySpec="&#x0964;"
+                 latin:moreKeys="&#x0965;" />
+            <!-- U+0999: "ঙ BENGALI LETTER NGA
+                 U+0999/U+09CD/U+0995: "ঙ্ক"
+                 U+0999/U+09CD/U+0996: "ঙ্খ"
+                 U+0999/U+09CD/U+0997: "ঙ্গ" -->
+            <Key latin:keySpec="&#x0999;"
+                 latin:moreKeys="&#x0999;&#x09CD;&#x0995;,&#x0999;&#x09CD;&#x0996;,&#x0999;&#x09CD;&#x0997;" />
+            <!-- U+099B: "ছ" BENGALI LETTER CHA -->
+            <Key latin:keySpec="&#x099B;" />
+            <!-- U+0983: "ঃ" BENGALI SIGN VISARGA -->
+            <Key latin:keySpec="&#x0983;" />
+            <!-- U+0981: "ঁ" BENGALI SIGN CANDRABINDU -->
+            <Key latin:keySpec="&#x0981;" />
+            <!-- U+09A3: "ণ" BENGALI LETTER NNA
+                 U+09A3/U+09CD/U+099F: "ণ্ট" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09A3/U+09CD/U+09A1: "ণ্ড" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                 U+09A3/U+09CD/U+09A3: "ণ্ণ" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA -->
+            <Key latin:keySpec="&#x09A3;"
+                 latin:moreKeys="&#x09A3;&#x09CD;&#x099F;,&#x09A3;&#x09CD;&#x09A1;,&#x09A3;&#x09CD;&#x09A3;" />
+            <!-- U+0982: "ং" BENGALI SIGN ANUSVARA -->
+            <Key latin:keySpec="&#x0982;" />
+            <!-- U+0990: "ঐ" BENGALI LETTER AI -->
+            <Key latin:keySpec="&#x0990;" />
+            <!-- U+0994: "ঔ" BENGALI LETTER AU -->
+            <Key latin:keySpec="&#x0994;" />
+        </case>
+        <default>
+            <!-- U+09AF: "য" BENGALI LETTER YA
+                 U+09CD/U+09AF: "্য" BENGALI SIGN VIRAMA/BENGALI LETTER YA -->
+            <Key
+                 latin:keySpec="&#x09AF;"
+                 latin:moreKeys="&#x09CD;&#x09AF;" />
+            <!-- U+09B7: "ষ" BENGALI LETTER SSA
+                 U+09B7/U+09CD/U+0995: "ষ্ক" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+09B7/U+09CD/U+099F: "ষ্ট" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09B7/U+09CD/U+09A0: "ষ্ঠ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTHA
+                 U+09B7/U+09CD/U+09A3: "ষ্ণ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                 U+09B7/U+09CD/U+09AA: "ষ্প" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09B7/U+09CD/U+09AB: "ষ্ফ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                 U+09B7/U+09CD/U+09AE: "ষ্ম" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER MA -->
+            <Key
+                 latin:keySpec="&#x09B7;"
+                 latin:moreKeys="&#x09B7;&#x09CD;&#x0995;,&#x09B7;&#x09CD;&#x099F;,&#x09B7;&#x09CD;&#x09A0;,&#x09B7;&#x09CD;&#x09A3;,&#x09B7;&#x09CD;&#x09AA;,&#x09B7;&#x09CD;&#x09AB;,&#x09B7;&#x09CD;&#x09AE;" />
+            <!-- U+099A: "চ" BENGALI LETTER CA
+                 U+099A/U+09CD/U+099A: "চ্চ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                 U+099A/U+09CD/U+099B: "চ্ছ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA -->
+            <Key
+                 latin:keySpec="&#x099A;"
+                 latin:moreKeys="&#x099A;&#x09CD;&#x099A;,&#x099A;&#x09CD;&#x099B;" />
+            <!-- U+09AD: "ভ" BENGALI LETTER BHA
+                 U+09AD/U+09CD/U+09AF: "ভ্" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09AD/U+09CD/U+09B0: "ভ্র" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AD/U+09CD/U+09B2: "ভ্ল" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                 latin:keySpec="&#x09AD;"
+                 latin:moreKeys="&#x09AD;&#x09CD;&#x09AF;,&#x09AD;&#x09CD;&#x09B0;,&#x09AD;&#x09CD;&#x09B2;" />
+            <!-- U+09AC: "ব" BENGALI LETTER BA
+                 U+09CD/U+09AC: "্ব" BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09AC/U+09CD/U+09B0: "ব্র" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AC/U+09CD/U+099C: "ব্জ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                 U+09AC/U+09CD/U+09A6: "ব্দ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09AC/U+09CD/U+09A7: "ব্ধ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09AC/U+09CD/U+09AC: "ব্ব" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09AC/U+09CD/U+09B2: "ব্ল" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                 U+09F1: "ৱ" BENGALI LETTER RA WITH MIDDLE DIAGONAL
+                 U+09F0: "ৰ" BENGALI LETTER RA WITH LOWER DIAGONAL -->
+            <Key
+                 latin:keySpec="&#x09AC;"
+                 latin:moreKeys="&#x09CD;&#x09AC;,&#x09AC;&#x09CD;&#x09B0;,&#x09AC;&#x09CD;&#x099C;,&#x09AC;&#x09CD;&#x09A6;,&#x09AC;&#x09CD;&#x09A7;,&#x09AC;&#x09CD;&#x09AC;,&#x09AC;&#x09CD;&#x09B2;,&#x09F1;,&#x09F0;" />
+            <!-- U+09A8: "ন" BENGALI LETTER NA
+                 U+09A8/U+09CD/U+09A4: "ন্ত" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09A8/U+09CD/U+09A5: "ন্থ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER THA
+                 U+09A8/U+09CD/U+099F: "ন্ট" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09A8/U+09CD/U+09A6: "ন্দ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09A8/U+09CD/U+09A7: "ন্ধ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09A8/U+09CD/U+09A1: "ন্ড" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                 U+09A8/U+09CD/U+09A8: "ন্ন" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09A8/U+09CD/U+09AC: "ন্ব" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A8/U+09CD/U+09AE: "ন্ম" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09A8/U+09CD/U+09B8: "ন্স" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER SA -->
+            <Key
+                 latin:keySpec="&#x09A8;"
+                 latin:moreKeys="&#x09A8;&#x09CD;&#x09A4;,&#x09A8;&#x09CD;&#x09A5;,&#x09A8;&#x09CD;&#x099F;,&#x09A8;&#x09CD;&#x09A6;,&#x09A8;&#x09CD;&#x09A7;,&#x09A8;&#x09CD;&#x09A1;,&#x09A8;&#x09CD;&#x09A8;,&#x09A8;&#x09CD;&#x09AC;,&#x09A8;&#x09CD;&#x09AE;,&#x09A8;&#x09CD;&#x09B8;" />
+            <!-- U+09AE: "ম" BENGALI LETTER MA
+                 U+09AE/U+09CD/U+09A8: "ম্ন" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09AE/U+09CD/U+09AA: "ম্প" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09AE/U+09CD/U+09AC: "ম্ব" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09AE/U+09CD/U+09AD: "ম্ভ" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                 U+09AE/U+09CD/U+09AE: "ম্ম" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09AE/U+09CD/U+09B0: "ম্র" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AE/U+09CD/U+09B2: "ম্ল" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                 latin:keySpec="&#x09AE;"
+                 latin:moreKeys=",&#x09AE;&#x09CD;&#x09A8;,&#x09AE;&#x09CD;&#x09AA;,&#x09AE;&#x09CD;&#x09AC;,&#x09AE;&#x09CD;&#x09AD;,&#x09AE;&#x09CD;&#x09AE;,&#x09AE;&#x09CD;&#x09B0;,&#x09AE;&#x09CD;&#x09B2;" />
+            <!-- U+098F: "এ" BENGALI LETTER E -->
+            <Key latin:keySpec="&#x098F;" />
+            <!-- U+0993: "ও" BENGALI LETTER O -->
+            <Key latin:keySpec="&#x0993;" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_uzbek1.xml b/java/res/xml/rowkeys_uzbek1.xml
new file mode 100644
index 0000000..967e9a7
--- /dev/null
+++ b/java/res/xml/rowkeys_uzbek1.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rowkeys_qwerty1" />
+    <!-- U+006F/U+02BB: "oʻ" LATIN SMALL LETTER O/MODIFIER LETTER TURNED COMMA -->
+    <Key
+        latin:keySpec="o&#x02BB;"
+        latin:keyLabelFlags="followKeyLetterRatio" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/rowkeys_uzbek2.xml b/java/res/xml/rowkeys_uzbek2.xml
new file mode 100644
index 0000000..b768a12
--- /dev/null
+++ b/java/res/xml/rowkeys_uzbek2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+    <!-- U+0067/U+02BB: "gʻ" LATIN SMALL LETTER G/MODIFIER LETTER TURNED COMMA -->
+    <Key
+        latin:keySpec="g&#x02BB;"
+        latin:keyLabelFlags="followKeyLetterRatio" />
+    <!-- U+02BC: "ʼ" MODIFIER LETTER APOSTROPHE -->
+    <Key latin:keySpec="&#x02BC;" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/rows_bengali_akkhor.xml b/java/res/xml/rows_bengali_akkhor.xml
new file mode 100644
index 0000000..1c7e772
--- /dev/null
+++ b/java/res/xml/rows_bengali_akkhor.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor1" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor2" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.711%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.8%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor3" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_uzbek.xml b/java/res/xml/rows_uzbek.xml
new file mode 100644
index 0000000..ae655d8
--- /dev/null
+++ b/java/res/xml/rows_uzbek.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek1" />
+    </Row>
+    <Row latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek2" />
+    </Row>
+    <Row latin:keyWidth="9.2%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="15%p"
+            latin:visualInsetsRight="1%p" />
+        <Spacer latin:keyWidth="2.8%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight"
+            latin:keyXPos="-15%p"
+            latin:visualInsetsLeft="1%p" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
index c937eee..5af3179 100644
--- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
@@ -84,8 +84,8 @@
     }
 
     @UsedForTesting
-    public static boolean isAvailable() {
-        return sCursorAnchorInfoClass.exists();
+    public boolean isAvailable() {
+        return sCursorAnchorInfoClass.exists() && mInstance != null;
     }
 
     private Object mInstance;
@@ -96,7 +96,7 @@
 
     @UsedForTesting
     public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) {
-        if (!isAvailable()) {
+        if (!sCursorAnchorInfoClass.exists()) {
             return new CursorAnchorInfoCompatWrapper(null);
         }
         return new CursorAnchorInfoCompatWrapper(instance);
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
index 6e4e328..c22717f 100644
--- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java
+++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
@@ -182,7 +182,7 @@
     private void layoutMain() {
         final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
 
-        if (info == null) {
+        if (info == null || !info.isAvailable()) {
             cancelLayoutInternalExpectedly("CursorAnchorInfo isn't available.");
             return;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
index 1e1188b..71ce768 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
@@ -27,6 +27,9 @@
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public class KeyboardParams {
     public KeyboardId mId;
     public int mThemeId;
@@ -67,7 +70,7 @@
     public final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
     public final KeyStylesSet mKeyStyles = new KeyStylesSet(mTextsSet);
 
-    public KeysCache mKeysCache;
+    @Nullable public KeysCache mKeysCache;
     public boolean mAllowRedundantMoreKeys;
 
     public int mMostCommonKeyHeight = 0;
@@ -96,7 +99,7 @@
         clearHistogram();
     }
 
-    public void onAddKey(final Key newKey) {
+    public void onAddKey(@Nonnull final Key newKey) {
         final Key key = (mKeysCache != null) ? mKeysCache.get(newKey) : newKey;
         final boolean isSpacer = key.isSpacer();
         if (isSpacer && key.getWidth() == 0) {
@@ -129,7 +132,10 @@
         mSortedKeys.clear();
         for (final Key key : allKeys) {
             final Key filteredKey = Key.removeRedundantMoreKeys(key, lettersOnBaseLayout);
-            mSortedKeys.add(mKeysCache.replace(key, filteredKey));
+            if (mKeysCache != null) {
+                mKeysCache.replace(key, filteredKey);
+            }
+            mSortedKeys.add(filteredKey);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index a778ee8..978194a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -83,24 +83,24 @@
 
     private static final String[] NAMES = {
     //  /* index:histogram */ "name",
-        /*   0:32 */ "morekeys_a",
-        /*   1:32 */ "morekeys_o",
-        /*   2:31 */ "morekeys_e",
-        /*   3:30 */ "morekeys_u",
-        /*   4:30 */ "keylabel_to_alpha",
-        /*   5:29 */ "morekeys_i",
-        /*   6:24 */ "morekeys_n",
-        /*   7:24 */ "morekeys_c",
+        /*   0:33 */ "morekeys_a",
+        /*   1:33 */ "morekeys_o",
+        /*   2:32 */ "morekeys_e",
+        /*   3:31 */ "morekeys_u",
+        /*   4:31 */ "keylabel_to_alpha",
+        /*   5:30 */ "morekeys_i",
+        /*   6:25 */ "morekeys_n",
+        /*   7:25 */ "morekeys_c",
         /*   8:23 */ "double_quotes",
-        /*   9:22 */ "single_quotes",
-        /*  10:21 */ "morekeys_s",
-        /*  11:18 */ "keyspec_currency",
-        /*  12:16 */ "morekeys_y",
-        /*  13:15 */ "morekeys_z",
+        /*   9:22 */ "morekeys_s",
+        /*  10:22 */ "single_quotes",
+        /*  11:19 */ "keyspec_currency",
+        /*  12:17 */ "morekeys_y",
+        /*  13:16 */ "morekeys_z",
         /*  14:14 */ "morekeys_d",
         /*  15:10 */ "morekeys_t",
         /*  16:10 */ "morekeys_l",
-        /*  17: 9 */ "morekeys_g",
+        /*  17:10 */ "morekeys_g",
         /*  18: 9 */ "single_angle_quotes",
         /*  19: 9 */ "double_angle_quotes",
         /*  20: 8 */ "morekeys_r",
@@ -139,54 +139,54 @@
         /*  53: 4 */ "morekeys_nordic_row2_11",
         /*  54: 4 */ "morekeys_punctuation",
         /*  55: 4 */ "keyspec_tablet_comma",
-        /*  56: 3 */ "keyspec_swiss_row1_11",
-        /*  57: 3 */ "keyspec_swiss_row2_10",
-        /*  58: 3 */ "keyspec_swiss_row2_11",
-        /*  59: 3 */ "morekeys_swiss_row1_11",
-        /*  60: 3 */ "morekeys_swiss_row2_10",
-        /*  61: 3 */ "morekeys_swiss_row2_11",
-        /*  62: 3 */ "morekeys_star",
-        /*  63: 3 */ "keyspec_left_parenthesis",
-        /*  64: 3 */ "keyspec_right_parenthesis",
-        /*  65: 3 */ "keyspec_left_square_bracket",
-        /*  66: 3 */ "keyspec_right_square_bracket",
-        /*  67: 3 */ "keyspec_left_curly_bracket",
-        /*  68: 3 */ "keyspec_right_curly_bracket",
-        /*  69: 3 */ "keyspec_less_than",
-        /*  70: 3 */ "keyspec_greater_than",
-        /*  71: 3 */ "keyspec_less_than_equal",
-        /*  72: 3 */ "keyspec_greater_than_equal",
-        /*  73: 3 */ "keyspec_left_double_angle_quote",
-        /*  74: 3 */ "keyspec_right_double_angle_quote",
-        /*  75: 3 */ "keyspec_left_single_angle_quote",
-        /*  76: 3 */ "keyspec_right_single_angle_quote",
-        /*  77: 3 */ "keyspec_comma",
-        /*  78: 3 */ "morekeys_tablet_comma",
-        /*  79: 3 */ "keyhintlabel_period",
-        /*  80: 3 */ "morekeys_tablet_period",
-        /*  81: 3 */ "morekeys_question",
-        /*  82: 2 */ "morekeys_h",
-        /*  83: 2 */ "morekeys_w",
-        /*  84: 2 */ "morekeys_east_slavic_row2_2",
-        /*  85: 2 */ "morekeys_cyrillic_u",
-        /*  86: 2 */ "morekeys_cyrillic_en",
-        /*  87: 2 */ "morekeys_cyrillic_ghe",
-        /*  88: 2 */ "morekeys_cyrillic_o",
-        /*  89: 2 */ "morekeys_cyrillic_i",
-        /*  90: 2 */ "keyspec_south_slavic_row1_6",
-        /*  91: 2 */ "keyspec_south_slavic_row2_11",
-        /*  92: 2 */ "keyspec_south_slavic_row3_1",
-        /*  93: 2 */ "keyspec_south_slavic_row3_8",
-        /*  94: 2 */ "morekeys_tablet_punctuation",
-        /*  95: 2 */ "keyspec_spanish_row2_10",
-        /*  96: 2 */ "morekeys_bullet",
-        /*  97: 2 */ "morekeys_left_parenthesis",
-        /*  98: 2 */ "morekeys_right_parenthesis",
-        /*  99: 2 */ "morekeys_arabic_diacritics",
-        /* 100: 2 */ "keyhintlabel_tablet_comma",
-        /* 101: 2 */ "keyspec_period",
-        /* 102: 2 */ "morekeys_period",
-        /* 103: 2 */ "keyspec_tablet_period",
+        /*  56: 4 */ "morekeys_tablet_period",
+        /*  57: 3 */ "keyspec_swiss_row1_11",
+        /*  58: 3 */ "keyspec_swiss_row2_10",
+        /*  59: 3 */ "keyspec_swiss_row2_11",
+        /*  60: 3 */ "morekeys_swiss_row1_11",
+        /*  61: 3 */ "morekeys_swiss_row2_10",
+        /*  62: 3 */ "morekeys_swiss_row2_11",
+        /*  63: 3 */ "morekeys_star",
+        /*  64: 3 */ "keyspec_left_parenthesis",
+        /*  65: 3 */ "keyspec_right_parenthesis",
+        /*  66: 3 */ "keyspec_left_square_bracket",
+        /*  67: 3 */ "keyspec_right_square_bracket",
+        /*  68: 3 */ "keyspec_left_curly_bracket",
+        /*  69: 3 */ "keyspec_right_curly_bracket",
+        /*  70: 3 */ "keyspec_less_than",
+        /*  71: 3 */ "keyspec_greater_than",
+        /*  72: 3 */ "keyspec_less_than_equal",
+        /*  73: 3 */ "keyspec_greater_than_equal",
+        /*  74: 3 */ "keyspec_left_double_angle_quote",
+        /*  75: 3 */ "keyspec_right_double_angle_quote",
+        /*  76: 3 */ "keyspec_left_single_angle_quote",
+        /*  77: 3 */ "keyspec_right_single_angle_quote",
+        /*  78: 3 */ "keyspec_comma",
+        /*  79: 3 */ "morekeys_tablet_comma",
+        /*  80: 3 */ "keyspec_period",
+        /*  81: 3 */ "keyhintlabel_period",
+        /*  82: 3 */ "morekeys_period",
+        /*  83: 3 */ "keyspec_tablet_period",
+        /*  84: 3 */ "morekeys_question",
+        /*  85: 2 */ "morekeys_h",
+        /*  86: 2 */ "morekeys_w",
+        /*  87: 2 */ "morekeys_east_slavic_row2_2",
+        /*  88: 2 */ "morekeys_cyrillic_u",
+        /*  89: 2 */ "morekeys_cyrillic_en",
+        /*  90: 2 */ "morekeys_cyrillic_ghe",
+        /*  91: 2 */ "morekeys_cyrillic_o",
+        /*  92: 2 */ "morekeys_cyrillic_i",
+        /*  93: 2 */ "keyspec_south_slavic_row1_6",
+        /*  94: 2 */ "keyspec_south_slavic_row2_11",
+        /*  95: 2 */ "keyspec_south_slavic_row3_1",
+        /*  96: 2 */ "keyspec_south_slavic_row3_8",
+        /*  97: 2 */ "morekeys_tablet_punctuation",
+        /*  98: 2 */ "keyspec_spanish_row2_10",
+        /*  99: 2 */ "morekeys_bullet",
+        /* 100: 2 */ "morekeys_left_parenthesis",
+        /* 101: 2 */ "morekeys_right_parenthesis",
+        /* 102: 2 */ "morekeys_arabic_diacritics",
+        /* 103: 2 */ "keyhintlabel_tablet_comma",
         /* 104: 2 */ "keyhintlabel_tablet_period",
         /* 105: 2 */ "keyspec_symbols_question",
         /* 106: 2 */ "keyspec_symbols_semicolon",
@@ -274,8 +274,8 @@
         EMPTY, EMPTY, EMPTY,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_lqm_rqm",
-        /* single_quotes */ "!text/single_lqm_rqm",
         /* morekeys_s */ EMPTY,
+        /* single_quotes */ "!text/single_lqm_rqm",
         /* keyspec_currency */ "$",
         /* morekeys_y ~ */
         EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
@@ -302,6 +302,7 @@
         /* ~ morekeys_nordic_row2_11 */
         /* morekeys_punctuation */ "!autoColumnOrder!8,\\,,?,!,#,!text/keyspec_right_parenthesis,!text/keyspec_left_parenthesis,/,;,',@,:,-,\",+,\\%,&",
         /* keyspec_tablet_comma */ ",",
+        /* morekeys_tablet_period */ "!text/morekeys_tablet_punctuation",
         /* keyspec_swiss_row1_11 ~ */
         EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
         /* ~ morekeys_swiss_row2_11 */
@@ -334,8 +335,11 @@
         // Comma key
         /* keyspec_comma */ ",",
         /* morekeys_tablet_comma */ EMPTY,
+        // Period key
+        /* keyspec_period */ ".",
         /* keyhintlabel_period */ EMPTY,
-        /* morekeys_tablet_period */ "!text/morekeys_tablet_punctuation",
+        /* morekeys_period */ "!text/morekeys_punctuation",
+        /* keyspec_tablet_period */ ".",
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "\u00BF",
         /* morekeys_h ~ */
@@ -352,13 +356,9 @@
         /* morekeys_bullet */ "\u266A,\u2665,\u2660,\u2666,\u2663",
         /* morekeys_left_parenthesis */ "!fixedColumnOrder!3,!text/keyspecs_left_parenthesis_more_keys",
         /* morekeys_right_parenthesis */ "!fixedColumnOrder!3,!text/keyspecs_right_parenthesis_more_keys",
-        /* morekeys_arabic_diacritics */ EMPTY,
-        /* keyhintlabel_tablet_comma */ EMPTY,
-        // Period key
-        /* keyspec_period */ ".",
-        /* morekeys_period */ "!text/morekeys_punctuation",
-        /* keyspec_tablet_period */ ".",
-        /* keyhintlabel_tablet_period */ EMPTY,
+        /* morekeys_arabic_diacritics ~ */
+        EMPTY, EMPTY, EMPTY,
+        /* ~ keyhintlabel_tablet_period */
         /* keyspec_symbols_question */ "?",
         /* keyspec_symbols_semicolon */ ";",
         /* keyspec_symbols_percent */ "%",
@@ -593,6 +593,7 @@
         // U+060C: "،" ARABIC COMMA
         // U+061B: "؛" ARABIC SEMICOLON
         /* keyspec_tablet_comma */ "\u060C",
+        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
         /* keyspec_swiss_row1_11 ~ */
         null, null, null, null, null, null,
         /* ~ morekeys_swiss_row2_11 */
@@ -622,9 +623,11 @@
         // U+060C: "،" ARABIC COMMA
         /* keyspec_comma */ "\u060C",
         /* morekeys_tablet_comma */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,\",\'",
+        /* keyspec_period */ null,
         // U+0651: "ّ" ARABIC SHADDA
         /* keyhintlabel_period */ "\u0651",
-        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
+        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
+        /* keyspec_tablet_period */ null,
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "?,\u00BF",
         /* morekeys_h ~ */
@@ -656,9 +659,6 @@
         // Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
         /* morekeys_arabic_diacritics */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
         /* keyhintlabel_tablet_comma */ "\u061F",
-        /* keyspec_period */ null,
-        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
-        /* keyspec_tablet_period */ null,
         /* keyhintlabel_tablet_period */ "\u0651",
         /* keyspec_symbols_question */ "\u061F",
         /* keyspec_symbols_semicolon */ "\u061B",
@@ -671,6 +671,7 @@
 
     /* Locale az_AZ: Azerbaijani (Azerbaijan) */
     private static final String[] TEXTS_az_AZ = {
+        // This is the same as Turkish
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
@@ -710,12 +711,12 @@
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u015F,\u00DF,\u015B,\u0161",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         /* morekeys_y */ "\u00FD",
@@ -742,9 +743,10 @@
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* morekeys_cyrillic_ie */ "\u0451",
@@ -780,6 +782,23 @@
         /* double_quotes */ "!text/double_9qm_lqm",
     };
 
+    /* Locale bn_BD: Bengali (Bangladesh) */
+    private static final String[] TEXTS_bn_BD = {
+        /* morekeys_a ~ */
+        null, null, null, null,
+        /* ~ morekeys_u */
+        // Label for "switch to alphabetic" key.
+        // U+0995: "क" BENGALI LETTER KA
+        // U+0996: "ख" BENGALI LETTER KHA
+        // U+0997: "ग" BENGALI LETTER GA
+        /* keylabel_to_alpha */ "\u0995\u0996\u0997",
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
+        // U+09F3: "৳" BENGALI RUPEE SIGN
+        /* keyspec_currency */ "\u09F3",
+    };
+
     /* Locale bn_IN: Bengali (India) */
     private static final String[] TEXTS_bn_IN = {
         /* morekeys_a ~ */
@@ -792,7 +811,7 @@
         /* keylabel_to_alpha */ "\u0995\u0996\u0997",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -865,7 +884,7 @@
         /* keyspec_tablet_comma ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ keyspec_south_slavic_row3_8 */
         /* morekeys_tablet_punctuation */ "!autoColumnOrder!8,\\,,',\u00B7,#,),(,/,;,@,:,-,\",+,\\%,&",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
@@ -925,11 +944,11 @@
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         /* morekeys_s */ "\u0161,\u00DF,\u015B",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -988,11 +1007,11 @@
         /* morekeys_n */ "\u00F1,\u0144",
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u00DF,\u015B,\u0161",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -1064,11 +1083,11 @@
         /* morekeys_n */ "\u00F1,\u0144",
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u00DF,\u015B,\u0161",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency ~ */
         null, null, null, null, null, null, null,
         /* ~ morekeys_g */
@@ -1077,8 +1096,8 @@
         /* morekeys_r ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null,
-        /* ~ keyspec_tablet_comma */
+        null, null, null, null, null, null, null,
+        /* ~ morekeys_tablet_period */
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* keyspec_swiss_row1_11 */ "\u00FC",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
@@ -1149,7 +1168,6 @@
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u00DF",
     };
@@ -1223,13 +1241,13 @@
         // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
         /* morekeys_c */ "\u0107,\u010D,\u00E7,\u010B",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u00DF,\u0161,\u015B,\u0219,\u015F",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX
@@ -1273,6 +1291,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_question */
         // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
         // U+0127: "ħ" LATIN SMALL LETTER H WITH STROKE
@@ -1286,7 +1305,7 @@
         /* keyspec_spanish_row2_10 */ "\u0135",
         /* morekeys_bullet ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null,
+        null, null, null, null,
         /* ~ label_wait_key */
         // U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX
         /* morekeys_v */ "w,\u0175",
@@ -1423,12 +1442,12 @@
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -1536,7 +1555,7 @@
         /* keylabel_to_alpha */ "\u0627\u200C\u0628\u200C\u067E",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+FDFC: "﷼" RIAL SIGN
         /* keyspec_currency */ "\uFDFC",
         /* morekeys_y ~ */
@@ -1586,6 +1605,7 @@
         // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
         // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
         /* keyspec_tablet_comma */ "\u060C",
+        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
         /* keyspec_swiss_row1_11 ~ */
         null, null, null, null, null, null,
         /* ~ morekeys_swiss_row2_11 */
@@ -1609,9 +1629,11 @@
         // U+060C: "،" ARABIC COMMA
         /* keyspec_comma */ "\u060C",
         /* morekeys_tablet_comma */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,!text/keyspec_left_double_angle_quote,!text/keyspec_right_double_angle_quote",
+        /* keyspec_period */ null,
         // U+064B: "ً" ARABIC FATHATAN
         /* keyhintlabel_period */ "\u064B",
-        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
+        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
+        /* keyspec_tablet_period */ null,
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "?,\u00BF",
         /* morekeys_h ~ */
@@ -1643,9 +1665,6 @@
         // Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
         /* morekeys_arabic_diacritics */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
         /* keyhintlabel_tablet_comma */ "\u061F",
-        /* keyspec_period */ null,
-        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
-        /* keyspec_tablet_period */ null,
         /* keyhintlabel_tablet_period */ "\u064B",
         /* keyspec_symbols_question */ "\u061F",
         /* keyspec_symbols_semicolon */ "\u061B",
@@ -1692,14 +1711,15 @@
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* morekeys_u */ "\u00FC",
         /* keylabel_to_alpha ~ */
-        null, null, null, null, null, null,
-        /* ~ single_quotes */
+        null, null, null, null, null,
+        /* ~ double_quotes */
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         /* morekeys_s */ "\u0161,\u00DF,\u015B",
-        /* keyspec_currency */ null,
-        /* morekeys_y */ null,
+        /* single_quotes ~ */
+        null, null, null,
+        /* ~ morekeys_y */
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
@@ -1780,8 +1800,8 @@
         /* morekeys_z ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keyspec_tablet_comma */
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ morekeys_tablet_period */
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         /* keyspec_swiss_row1_11 */ "\u00E8",
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
@@ -1862,7 +1882,7 @@
         /* keylabel_to_alpha */ "\u0915\u0916\u0917",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
         /* morekeys_y ~ */
@@ -1901,13 +1921,26 @@
         /* additional_morekeys_symbols_8 */ "8",
         /* additional_morekeys_symbols_9 */ "9",
         /* additional_morekeys_symbols_0 */ "0",
+        /* morekeys_nordic_row2_11 ~ */
+        null, null, null,
+        /* ~ keyspec_tablet_comma */
+        /* morekeys_tablet_period */ "!autoColumnOrder!8,\\,,.,',#,),(,/,;,@,:,-,\",+,\\%,&",
+        /* keyspec_swiss_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,
+        /* ~ morekeys_tablet_comma */
+        // U+0964: "।" DEVANAGARI DANDA
+        /* keyspec_period */ "\u0964",
+        /* keyhintlabel_period */ null,
+        /* morekeys_period */ "!autoColumnOrder!9,\\,,.,?,!,#,),(,/,;,',@,:,-,\",+,\\%,&",
+        /* keyspec_tablet_period */ "\u0964",
     };
 
     /* Locale hi_ZZ: Hindi (ZZ) */
     private static final String[] TEXTS_hi_ZZ = {
         /* morekeys_a ~ */
         null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
         /* morekeys_y ~ */
@@ -1942,11 +1975,11 @@
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u010D,\u0107,\u00E7",
         /* double_quotes */ "!text/double_9qm_rqm",
-        /* single_quotes */ "!text/single_9qm_rqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u0161,\u015B,\u00DF",
+        /* single_quotes */ "!text/single_9qm_rqm",
         /* keyspec_currency */ null,
         /* morekeys_y */ null,
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
@@ -2009,9 +2042,10 @@
         /* morekeys_n */ null,
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_rqm",
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_rqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_g */
         /* single_angle_quotes */ "!text/single_raqm_laqm",
         /* double_angle_quotes */ "!text/double_raqm_laqm",
@@ -2045,6 +2079,7 @@
         // U+055F: "՟" ARMENIAN ABBREVIATION MARK
         /* morekeys_punctuation */ "!autoColumnOrder!8,\\,,\u055E,\u055C,.,\u055A,\u0559,?,!,\u055D,\u055B,\u058A,\u00BB,\u00AB,\u055F,;,:",
         /* keyspec_tablet_comma */ "\u055D",
+        /* morekeys_tablet_period */ "!text/morekeys_punctuation",
         /* keyspec_swiss_row1_11 ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null,
@@ -2056,22 +2091,19 @@
         // U+055D: "՝" ARMENIAN COMMA
         /* keyspec_comma */ "\u055D",
         /* morekeys_tablet_comma */ null,
+        // U+0589: "։" ARMENIAN FULL STOP
+        /* keyspec_period */ "\u0589",
         /* keyhintlabel_period */ null,
-        /* morekeys_tablet_period */ "!text/morekeys_punctuation",
+        /* morekeys_period */ null,
+        /* keyspec_tablet_period */ "\u0589",
         // U+055E: "՞" ARMENIAN QUESTION MARK
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "\u055E,\u00BF",
         /* morekeys_h ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null,
-        /* ~ keyhintlabel_tablet_comma */
-        // U+0589: "։" ARMENIAN FULL STOP
-        /* keyspec_period */ "\u0589",
-        /* morekeys_period */ null,
-        /* keyspec_tablet_period */ "\u0589",
-        /* keyhintlabel_tablet_period ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_greater_than */
         // U+055C: "՜" ARMENIAN EXCLAMATION MARK
         // U+00A1: "¡" INVERTED EXCLAMATION MARK
@@ -2123,8 +2155,8 @@
         /* morekeys_n */ null,
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -2184,8 +2216,8 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
-        /* ~ keyspec_tablet_comma */
+        null, null, null, null, null, null,
+        /* ~ morekeys_tablet_period */
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* keyspec_swiss_row1_11 */ "\u00FC",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
@@ -2214,15 +2246,15 @@
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_rqm_9qm",
-        /* single_quotes */ "!text/single_rqm_9qm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_rqm_9qm",
         // U+20AA: "₪" NEW SHEQEL SIGN
         /* keyspec_currency */ "\u20AA",
         /* morekeys_y ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
+        null, null, null, null, null, null,
         /* ~ morekeys_swiss_row2_11 */
         // U+2605: "★" BLACK STAR
         /* morekeys_star */ "\u2605",
@@ -2252,7 +2284,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null,
         /* ~ morekeys_currency_dollar */
         // U+00B1: "±" PLUS-MINUS SIGN
         // U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
@@ -2273,6 +2305,7 @@
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
     };
 
@@ -2309,7 +2342,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_w */
         // U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
         /* morekeys_east_slavic_row2_2 */ "\u0456",
@@ -2325,7 +2358,7 @@
         /* morekeys_cyrillic_i ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null,
+        null, null, null, null,
         /* ~ keyspec_x */
         // U+04BB: "һ" CYRILLIC SMALL LETTER SHHA
         /* morekeys_east_slavic_row2_11 */ "\u04BB",
@@ -2372,7 +2405,7 @@
         /* keylabel_to_alpha */ "\u0C85\u0C86\u0C87",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -2410,7 +2443,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_east_slavic_row2_2 */
         // U+04AF: "ү" CYRILLIC SMALL LETTER STRAIGHT U
         /* morekeys_cyrillic_u */ "\u04AF",
@@ -2433,7 +2466,7 @@
         /* keylabel_to_alpha */ "\u0E81\u0E82\u0E84",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20AD: "₭" KIP SIGN
         /* keyspec_currency */ "\u20AD",
     };
@@ -2496,12 +2529,12 @@
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -2590,12 +2623,12 @@
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -2641,9 +2674,10 @@
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_k */
         // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE
         /* morekeys_cyrillic_ie */ "\u0450",
@@ -2652,7 +2686,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_cyrillic_o */
         // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
         /* morekeys_cyrillic_i */ "\u045D",
@@ -2676,7 +2710,7 @@
         /* keylabel_to_alpha */ "\u0D05",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -2693,7 +2727,7 @@
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20AE: "₮" TUGRIK SIGN
         /* keyspec_currency */ "\u20AE",
     };
@@ -2710,7 +2744,7 @@
         /* keylabel_to_alpha */ "\u0915\u0916\u0917",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
         /* morekeys_y ~ */
@@ -2771,22 +2805,19 @@
         // U+104A: "၊" MYANMAR SIGN LITTLE SECTION
         // U+104B: "။" MYANMAR SIGN SECTION
         /* keyspec_tablet_comma */ "\u104A",
-        /* keyspec_swiss_row1_11 ~ */
+        /* morekeys_tablet_period ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null,
         /* ~ keyspec_comma */
         /* morekeys_tablet_comma */ "\\,",
-        /* keyhintlabel_period */ "\u104A",
-        /* morekeys_tablet_period ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keyspec_south_slavic_row3_8 */
-        /* morekeys_tablet_punctuation */ "!autoColumnOrder!8,.,',#,),(,/,;,@,...,:,-,\",+,\\%,&",
-        /* keyspec_spanish_row2_10 ~ */
-        null, null, null, null, null, null,
-        /* ~ keyhintlabel_tablet_comma */
         /* keyspec_period */ "\u104B",
+        /* keyhintlabel_period */ "\u104A",
         /* morekeys_period */ null,
         /* keyspec_tablet_period */ "\u104B",
+        /* morekeys_question ~ */
+        null, null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ keyspec_south_slavic_row3_8 */
+        /* morekeys_tablet_punctuation */ "!autoColumnOrder!8,.,',#,),(,/,;,@,...,:,-,\",+,\\%,&",
     };
 
     /* Locale nb: Norwegian Bokmål */
@@ -2827,9 +2858,10 @@
         null, null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_rqm",
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_rqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_cyrillic_ie */
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         /* keyspec_nordic_row1_11 */ "\u00E5",
@@ -2859,7 +2891,7 @@
         /* keylabel_to_alpha */ "\u0915\u0916\u0917",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+0930/U+0941/U+002E "रु." NEPALESE RUPEE SIGN
         /* keyspec_currency */ "\u0930\u0941.",
         /* morekeys_y ~ */
@@ -2948,8 +2980,8 @@
         /* morekeys_n */ "\u00F1,\u0144",
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_rqm",
-        /* single_quotes */ "!text/single_9qm_rqm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_9qm_rqm",
         /* keyspec_currency */ null,
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
         /* morekeys_y */ "\u0133",
@@ -2995,11 +3027,11 @@
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u0107,\u00E7,\u010D",
         /* double_quotes */ "!text/double_9qm_rqm",
-        /* single_quotes */ "!text/single_9qm_rqm",
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u015B,\u00DF,\u0161",
+        /* single_quotes */ "!text/single_9qm_rqm",
         /* keyspec_currency */ null,
         /* morekeys_y */ null,
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
@@ -3100,12 +3132,12 @@
         /* morekeys_n */ null,
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_rqm",
-        /* single_quotes */ "!text/single_9qm_rqm",
         // U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u0219,\u00DF,\u015B,\u0161",
+        /* single_quotes */ "!text/single_9qm_rqm",
         /* keyspec_currency ~ */
         null, null, null, null,
         /* ~ morekeys_d */
@@ -3127,9 +3159,10 @@
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* morekeys_cyrillic_ie */ "\u0451",
@@ -3159,7 +3192,7 @@
         /* keylabel_to_alpha */ "\u0D85,\u0D86",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+0DBB/U+0DD4: "රු" SINHALA LETTER RAYANNA/SINHALA VOWEL SIGN KETTI PAA-PILLA
         /* keyspec_currency */ "\u0DBB\u0DD4",
     };
@@ -3222,12 +3255,12 @@
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -3268,9 +3301,9 @@
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u0161",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         /* morekeys_y */ null,
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
@@ -3299,9 +3332,10 @@
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_g */
         /* single_angle_quotes */ "!text/single_raqm_laqm",
         /* double_angle_quotes */ "!text/double_raqm_laqm",
@@ -3314,7 +3348,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_cyrillic_o */
         // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
         /* morekeys_cyrillic_i */ "\u045D",
@@ -3361,11 +3395,11 @@
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u0107,%",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u0161,%",
-        /* keyspec_currency */ null,
-        /* morekeys_y */ null,
+        /* single_quotes ~ */
+        null, null, null,
+        /* ~ morekeys_y */
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         /* morekeys_z */ "\u017E,%",
         // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
@@ -3436,12 +3470,12 @@
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u015B,\u0161,\u015F,\u00DF",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
@@ -3527,11 +3561,10 @@
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u00DF",
-        /* keyspec_currency ~ */
-        null, null, null, null, null, null,
+        /* single_quotes ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_l */
         /* morekeys_g */ "g\'",
     };
@@ -3548,7 +3581,7 @@
         /* keylabel_to_alpha */ "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+0BF9: "௹" TAMIL RUPEE SIGN
         /* keyspec_currency */ "\u0BF9",
     };
@@ -3565,7 +3598,7 @@
         /* keylabel_to_alpha */ "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+0DBB/U+0DD4: "රු" SINHALA LETTER RAYANNA/SINHALA VOWEL SIGN KETTI PAA-PILLA
         /* keyspec_currency */ "\u0DBB\u0DD4",
     };
@@ -3594,7 +3627,7 @@
         /* keylabel_to_alpha */ "\u0C05\u0C06\u0C07",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -3611,7 +3644,7 @@
         /* keylabel_to_alpha */ "\u0E01\u0E02\u0E04",
         /* morekeys_i ~ */
         null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT
         /* keyspec_currency */ "\u0E3F",
     };
@@ -3711,12 +3744,12 @@
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u015F,\u00DF,\u015B,\u0161",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         /* morekeys_y */ "\u00FD",
@@ -3743,8 +3776,8 @@
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* single_quotes */ "!text/single_9qm_lqm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_9qm_lqm",
         // U+20B4: "₴" HRYVNIA SIGN
         /* keyspec_currency */ "\u20B4",
         /* morekeys_y ~ */
@@ -3764,7 +3797,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_w */
         // U+0457: "ї" CYRILLIC SMALL LETTER YI
         /* morekeys_east_slavic_row2_2 */ "\u0457",
@@ -3774,6 +3807,66 @@
         /* morekeys_cyrillic_ghe */ "\u0491",
     };
 
+    /* Locale uz_UZ: Uzbek (Uzbekistan) */
+    private static final String[] TEXTS_uz_UZ = {
+        // This is the same as Turkish
+        // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+        // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+        /* morekeys_a */ "\u00E2,\u00E4,\u00E1",
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+        // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+        // U+0153: "œ" LATIN SMALL LIGATURE OE
+        // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+        // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+        // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+        // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+        // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+        /* morekeys_o */ "\u00F6,\u00F4,\u0153,\u00F2,\u00F3,\u00F5,\u00F8,\u014D",
+        // U+0259: "ə" LATIN SMALL LETTER SCHWA
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        /* morekeys_e */ "\u0259,\u00E9",
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+        /* keylabel_to_alpha */ null,
+        // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+        // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+        // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+        // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+        // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+        // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+        // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+        /* morekeys_i */ "\u0131,\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u0148,\u00F1",
+        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+        /* morekeys_c */ "\u00E7,\u0107,\u010D",
+        /* double_quotes */ null,
+        // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+        // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+        // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+        // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+        /* morekeys_s */ "\u015F,\u00DF,\u015B,\u0161",
+        /* single_quotes */ null,
+        /* keyspec_currency */ null,
+        // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+        /* morekeys_y */ "\u00FD",
+        // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+        /* morekeys_z */ "\u017E",
+        /* morekeys_d ~ */
+        null, null, null,
+        /* ~ morekeys_l */
+        // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+        /* morekeys_g */ "\u011F",
+    };
+
     /* Locale vi: Vietnamese */
     private static final String[] TEXTS_vi = {
         // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
@@ -3845,7 +3938,7 @@
         /* morekeys_i */ "\u00EC,\u00ED,\u1EC9,\u0129,\u1ECB",
         /* morekeys_n ~ */
         null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20AB: "₫" DONG SIGN
         /* keyspec_currency */ "\u20AB",
         // U+1EF3: "ỳ" LATIN SMALL LETTER Y WITH GRAVE
@@ -3904,7 +3997,6 @@
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u00DF",
     };
@@ -3982,7 +4074,6 @@
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u0109,\u010B,\u010D",
         /* double_quotes */ null,
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX
@@ -3990,6 +4081,7 @@
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+017F: "ſ" LATIN SMALL LETTER LONG S
         /* morekeys_s */ "\u00DF,\u015B,\u015D,\u015F,\u0161,\u017F",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX
@@ -4034,6 +4126,7 @@
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_question */
         // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
         /* morekeys_h */ "\u0125",
@@ -4042,7 +4135,7 @@
         /* morekeys_east_slavic_row2_2 ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
+        null, null,
         /* ~ morekeys_v */
         // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
         /* morekeys_j */ "\u0135",
@@ -4056,42 +4149,43 @@
         "az_AZ"  , TEXTS_az_AZ, /*  11/ 18 Azerbaijani (Azerbaijan) */
         "be_BY"  , TEXTS_be_BY, /*   9/ 32 Belarusian (Belarus) */
         "bg"     , TEXTS_bg,    /*   2/  9 Bulgarian */
+        "bn_BD"  , TEXTS_bn_BD, /*   2/ 12 Bengali (Bangladesh) */
         "bn_IN"  , TEXTS_bn_IN, /*   2/ 12 Bengali (India) */
-        "ca"     , TEXTS_ca,    /*  11/ 96 Catalan */
+        "ca"     , TEXTS_ca,    /*  11/ 99 Catalan */
         "cs"     , TEXTS_cs,    /*  17/ 21 Czech */
         "da"     , TEXTS_da,    /*  19/ 54 Danish */
-        "de"     , TEXTS_de,    /*  16/ 62 German */
+        "de"     , TEXTS_de,    /*  16/ 63 German */
         "el"     , TEXTS_el,    /*   1/  5 Greek */
-        "en"     , TEXTS_en,    /*   8/ 11 English */
+        "en"     , TEXTS_en,    /*   8/ 10 English */
         "eo"     , TEXTS_eo,    /*  26/126 Esperanto */
         "es"     , TEXTS_es,    /*   8/ 55 Spanish */
         "et_EE"  , TEXTS_et_EE, /*  22/ 27 Estonian (Estonia) */
         "eu_ES"  , TEXTS_eu_ES, /*   7/  8 Basque (Spain) */
         "fa"     , TEXTS_fa,    /*  58/133 Persian */
         "fi"     , TEXTS_fi,    /*  10/ 54 Finnish */
-        "fr"     , TEXTS_fr,    /*  13/ 62 French */
+        "fr"     , TEXTS_fr,    /*  13/ 63 French */
         "gl_ES"  , TEXTS_gl_ES, /*   7/  8 Gallegan (Spain) */
-        "hi"     , TEXTS_hi,    /*  23/ 53 Hindi */
+        "hi"     , TEXTS_hi,    /*  27/ 84 Hindi */
         "hi_ZZ"  , TEXTS_hi_ZZ, /*   9/118 Hindi (ZZ) */
         "hr"     , TEXTS_hr,    /*   9/ 20 Croatian */
         "hu"     , TEXTS_hu,    /*   9/ 20 Hungarian */
         "hy_AM"  , TEXTS_hy_AM, /*   9/134 Armenian (Armenia) */
         "is"     , TEXTS_is,    /*  10/ 16 Icelandic */
-        "it"     , TEXTS_it,    /*  11/ 62 Italian */
+        "it"     , TEXTS_it,    /*  11/ 63 Italian */
         "iw"     , TEXTS_iw,    /*  20/131 Hebrew */
-        "ka_GE"  , TEXTS_ka_GE, /*   3/ 10 Georgian (Georgia) */
+        "ka_GE"  , TEXTS_ka_GE, /*   3/ 11 Georgian (Georgia) */
         "kk"     , TEXTS_kk,    /*  15/129 Kazakh */
         "km_KH"  , TEXTS_km_KH, /*   2/130 Khmer (Cambodia) */
         "kn_IN"  , TEXTS_kn_IN, /*   2/ 12 Kannada (India) */
-        "ky"     , TEXTS_ky,    /*  10/ 89 Kirghiz */
+        "ky"     , TEXTS_ky,    /*  10/ 92 Kirghiz */
         "lo_LA"  , TEXTS_lo_LA, /*   2/ 12 Lao (Laos) */
         "lt"     , TEXTS_lt,    /*  18/ 22 Lithuanian */
         "lv"     , TEXTS_lv,    /*  18/ 22 Latvian */
-        "mk"     , TEXTS_mk,    /*   9/ 94 Macedonian */
+        "mk"     , TEXTS_mk,    /*   9/ 97 Macedonian */
         "ml_IN"  , TEXTS_ml_IN, /*   2/ 12 Malayalam (India) */
         "mn_MN"  , TEXTS_mn_MN, /*   2/ 12 Mongolian (Mongolia) */
         "mr_IN"  , TEXTS_mr_IN, /*  23/ 53 Marathi (India) */
-        "my_MM"  , TEXTS_my_MM, /*   8/104 Burmese (Myanmar) */
+        "my_MM"  , TEXTS_my_MM, /*   8/ 98 Burmese (Myanmar) */
         "nb"     , TEXTS_nb,    /*  11/ 54 Norwegian Bokmål */
         "ne_NP"  , TEXTS_ne_NP, /*  23/ 53 Nepali (Nepal) */
         "nl"     , TEXTS_nl,    /*   9/ 13 Dutch */
@@ -4103,7 +4197,7 @@
         "si_LK"  , TEXTS_si_LK, /*   2/ 12 Sinhalese (Sri Lanka) */
         "sk"     , TEXTS_sk,    /*  20/ 22 Slovak */
         "sl"     , TEXTS_sl,    /*   8/ 20 Slovenian */
-        "sr"     , TEXTS_sr,    /*  11/ 94 Serbian */
+        "sr"     , TEXTS_sr,    /*  11/ 97 Serbian */
         "sr_ZZ"  , TEXTS_sr_ZZ, /*  14/118 Serbian (ZZ) */
         "sv"     , TEXTS_sv,    /*  21/ 54 Swedish */
         "sw"     , TEXTS_sw,    /*   9/ 18 Swahili */
@@ -4114,9 +4208,10 @@
         "th"     , TEXTS_th,    /*   2/ 12 Thai */
         "tl"     , TEXTS_tl,    /*   7/  8 Tagalog */
         "tr"     , TEXTS_tr,    /*  11/ 18 Turkish */
-        "uk"     , TEXTS_uk,    /*  11/ 88 Ukrainian */
+        "uk"     , TEXTS_uk,    /*  11/ 91 Ukrainian */
+        "uz_UZ"  , TEXTS_uz_UZ, /*  11/ 18 Uzbek (Uzbekistan) */
         "vi"     , TEXTS_vi,    /*   8/ 15 Vietnamese */
-        "zu"     , TEXTS_zu,    /*   8/ 11 Zulu */
+        "zu"     , TEXTS_zu,    /*   8/ 10 Zulu */
         "zz"     , TEXTS_zz,    /*  19/120 Alphabet */
     };
 
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 1da33ed..6f3c48c 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -199,6 +199,9 @@
             int[] word, int probability, int timestamp);
     private static native boolean removeNgramEntryNative(long dict,
             int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray, int[] word);
+    private static native boolean updateCounterNative(long dict,
+            int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray,
+            int[] word, boolean isValidWord, int count, int timestamp);
     private static native int addMultipleDictionaryEntriesNative(long dict,
             LanguageModelParam[] languageModelParams, int startIndex);
     private static native String getPropertyNative(long dict, String query);
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 5aae010..099d485 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -247,7 +247,6 @@
             case MSG_RESUME_SUGGESTIONS:
                 latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor(
                         latinIme.mSettings.getCurrent(),
-                        msg.arg1 == ARG1_TRUE /* shouldIncludeResumedWordInSuggestions */,
                         latinIme.mKeyboardSwitcher.getCurrentKeyboardScriptId());
                 break;
             case MSG_REOPEN_DICTIONARIES:
@@ -288,8 +287,7 @@
             sendMessage(obtainMessage(MSG_REOPEN_DICTIONARIES));
         }
 
-        public void postResumeSuggestions(final boolean shouldIncludeResumedWordInSuggestions,
-                final boolean shouldDelay) {
+        public void postResumeSuggestions(final boolean shouldDelay) {
             final LatinIME latinIme = getOwnerInstance();
             if (latinIme == null) {
                 return;
@@ -299,13 +297,10 @@
             }
             removeMessages(MSG_RESUME_SUGGESTIONS);
             if (shouldDelay) {
-                sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS,
-                        shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
-                        0 /* ignored */), mDelayInMillisecondsToUpdateSuggestions);
+                sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS),
+                        mDelayInMillisecondsToUpdateSuggestions);
             } else {
-                sendMessage(obtainMessage(MSG_RESUME_SUGGESTIONS,
-                        shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
-                        0 /* ignored */));
+                sendMessage(obtainMessage(MSG_RESUME_SUGGESTIONS));
             }
         }
 
@@ -622,8 +617,7 @@
         }
         if (mHandler.hasPendingWaitForDictionaryLoad()) {
             mHandler.cancelWaitForDictionaryLoad();
-            mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
-                    false /* shouldDelay */);
+            mHandler.postResumeSuggestions(false /* shouldDelay */);
         }
     }
 
@@ -926,11 +920,12 @@
                 // mLastSelection{Start,End} are reset later in this method, no need to do it here
                 needToCallLoadKeyboardLater = true;
             } else {
-                // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
-                // effort to work around this bug.
+                // When rotating, and when input is starting again in a field from where the focus
+                // didn't move (the keyboard having been closed with the back key),
+                // initialSelStart and initialSelEnd sometimes are lying. Make a best effort to
+                // work around this bug.
                 mInputLogic.mConnection.tryFixLyingCursorPosition();
-                mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
-                        true /* shouldDelay */);
+                mHandler.postResumeSuggestions(true /* shouldDelay */);
                 needToCallLoadKeyboardLater = false;
             }
         } else {
diff --git a/java/src/com/android/inputmethod/latin/NgramContext.java b/java/src/com/android/inputmethod/latin/NgramContext.java
index c35c6e2..6d43858 100644
--- a/java/src/com/android/inputmethod/latin/NgramContext.java
+++ b/java/src/com/android/inputmethod/latin/NgramContext.java
@@ -169,8 +169,14 @@
 
     @Override
     public int hashCode() {
-        // Just for having equals().
-        return mPrevWordsInfo[0].hashCode();
+        int hashValue = 0;
+        for (final WordInfo wordInfo : mPrevWordsInfo) {
+            if (wordInfo == null || !WordInfo.EMPTY_WORD_INFO.equals(wordInfo)) {
+                break;
+            }
+            hashValue ^= wordInfo.hashCode();
+        }
+        return hashValue;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 7507061..a7ea2a1 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -849,8 +849,9 @@
 
     /**
      * Try to get the text from the editor to expose lies the framework may have been
-     * telling us. Concretely, when the device rotates, the frameworks tells us about where the
-     * cursor used to be initially in the editor at the time it first received the focus; this
+     * telling us. Concretely, when the device rotates and when the keyboard reopens in the same
+     * text field after having been closed with the back key, the frameworks tells us about where
+     * the cursor used to be initially in the editor at the time it first received the focus; this
      * may be completely different from the place it is upon rotation. Since we don't have any
      * means to get the real value, try at least to ask the text view for some characters and
      * detect the most damaging cases: when the cursor position is declared to be much smaller
@@ -859,7 +860,20 @@
     public void tryFixLyingCursorPosition() {
         final CharSequence textBeforeCursor = getTextBeforeCursor(
                 Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
-        if (null == textBeforeCursor) {
+        final CharSequence selectedText = mIC.getSelectedText(0 /* flags */);
+        if (null == textBeforeCursor ||
+                (!TextUtils.isEmpty(selectedText) && mExpectedSelEnd == mExpectedSelStart)) {
+            // If textBeforeCursor is null, we have no idea what kind of text field we have or if
+            // thinking about the "cursor position" actually makes any sense. In this case we
+            // remember a meaningless cursor position. Contrast this with an empty string, which is
+            // valid and should mean the cursor is at the start of the text.
+            // Also, if we expect we don't have a selection but we DO have non-empty selected text,
+            // then the framework lied to us about the cursor position. In this case, we should just
+            // revert to the most basic behavior possible for the next action (backspace in
+            // particular comes to mind), so we remember a meaningless cursor position which should
+            // result in degraded behavior from the next input.
+            // Interestingly, in either case, chances are any action the user takes next will result
+            // in a call to onUpdateSelection, which should set things right.
             mExpectedSelStart = mExpectedSelEnd = Constants.NOT_A_CURSOR_POSITION;
         } else {
             final int textLength = textBeforeCursor.length();
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 27af161..b4a1c3e 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -435,8 +435,7 @@
         // removed.
         mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
         // We moved the cursor. If we are touching a word, we need to resume suggestion.
-        mLatinIME.mHandler.postResumeSuggestions(false /* shouldIncludeResumedWordInSuggestions */,
-                true /* shouldDelay */);
+        mLatinIME.mHandler.postResumeSuggestions(true /* shouldDelay */);
         // Stop the last recapitalization, if started.
         mRecapitalizeStatus.stop();
         return true;
@@ -1127,19 +1126,21 @@
                 StatsUtils.onBackspaceSelectedText(numCharsDeleted);
             } else {
                 // There is no selection, just delete one character.
-                if (Constants.NOT_A_CURSOR_POSITION == mConnection.getExpectedSelectionEnd()) {
-                    // This should never happen.
-                    Log.e(TAG, "Backspace when we don't know the selection position");
-                }
-                if (inputTransaction.mSettingsValues.isBeforeJellyBean() ||
-                        inputTransaction.mSettingsValues.mInputAttributes.isTypeNull()) {
-                    // There are two possible reasons to send a key event: either the field has
+                if (inputTransaction.mSettingsValues.isBeforeJellyBean()
+                        || inputTransaction.mSettingsValues.mInputAttributes.isTypeNull()
+                        || Constants.NOT_A_CURSOR_POSITION
+                                == mConnection.getExpectedSelectionEnd()) {
+                    // There are three possible reasons to send a key event: either the field has
                     // type TYPE_NULL, in which case the keyboard should send events, or we are
-                    // running in backward compatibility mode. Before Jelly bean, the keyboard
-                    // would simulate a hardware keyboard event on pressing enter or delete. This
-                    // is bad for many reasons (there are race conditions with commits) but some
-                    // applications are relying on this behavior so we continue to support it for
-                    // older apps, so we retain this behavior if the app has target SDK < JellyBean.
+                    // running in backward compatibility mode, or we don't know the cursor position.
+                    // Before Jelly bean, the keyboard would simulate a hardware keyboard event on
+                    // pressing enter or delete. This is bad for many reasons (there are race
+                    // conditions with commits) but some applications are relying on this behavior
+                    // so we continue to support it for older apps, so we retain this behavior if
+                    // the app has target SDK < JellyBean.
+                    // As for the case where we don't know the cursor position, it can happen
+                    // because of bugs in the framework. But the framework should know, so the next
+                    // best thing is to leave it to whatever it thinks is best.
                     sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
                     int totalDeletedLength = 1;
                     if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
@@ -1184,7 +1185,7 @@
                     && !mConnection.isCursorFollowedByWordCharacter(
                             inputTransaction.mSettingsValues.mSpacingAndPunctuations)) {
                 restartSuggestionsOnWordTouchedByCursor(inputTransaction.mSettingsValues,
-                        true /* shouldIncludeResumedWordInSuggestions */, currentKeyboardScriptId);
+                        currentKeyboardScriptId);
             }
         }
     }
@@ -1440,12 +1441,10 @@
      * do nothing.
      *
      * @param settingsValues the current values of the settings.
-     * @param shouldIncludeResumedWordInSuggestions whether to include the word on which we resume
      *   suggestions in the suggestion list.
      */
     // TODO: make this private.
     public void restartSuggestionsOnWordTouchedByCursor(final SettingsValues settingsValues,
-            final boolean shouldIncludeResumedWordInSuggestions,
             // TODO: remove this argument, put it into settingsValues
             final int currentKeyboardScriptId) {
         // HACK: We may want to special-case some apps that exhibit bad behavior in case of
@@ -1493,13 +1492,6 @@
         if (numberOfCharsInWordBeforeCursor > expectedCursorPosition) return;
         final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
         final String typedWord = range.mWord.toString();
-        if (shouldIncludeResumedWordInSuggestions) {
-            suggestions.add(new SuggestedWordInfo(typedWord,
-                    SuggestedWords.MAX_SUGGESTIONS + 1,
-                    SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
-                    SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
-                    SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
-        }
         if (!isResumableWord(settingsValues, typedWord)) {
             mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
             return;
@@ -1532,7 +1524,7 @@
         mConnection.maybeMoveTheCursorAroundAndRestoreToWorkaroundABug();
         mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
                 expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor());
-        if (suggestions.size() <= (shouldIncludeResumedWordInSuggestions ? 1 : 0)) {
+        if (suggestions.size() <= 0) {
             // If there weren't any suggestion spans on this word, suggestions#size() will be 1
             // if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
             // have no useful suggestions, so we will try to compute some for it instead.
@@ -1542,8 +1534,7 @@
                         public void onGetSuggestedWords(
                                 final SuggestedWords suggestedWordsIncludingTypedWord) {
                             final SuggestedWords suggestedWords;
-                            if (suggestedWordsIncludingTypedWord.size() > 1
-                                    && !shouldIncludeResumedWordInSuggestions) {
+                            if (suggestedWordsIncludingTypedWord.size() > 1) {
                                 // We were able to compute new suggestions for this word.
                                 // Remove the typed word, since we don't want to display it in this
                                 // case. The #getSuggestedWordsExcludingTypedWordForRecorrection()
@@ -1591,6 +1582,10 @@
         final String committedWordString = committedWord.toString();
         final int cancelLength = committedWord.length();
         final String separatorString = mLastComposedWord.mSeparatorString;
+        // If our separator is a space, we won't actually commit it,
+        // but set the space state to PHANTOM so that a space will be inserted
+        // on the next keypress
+        final boolean usePhantomSpace = separatorString.equals(Constants.STRING_SPACE);
         // We want java chars, not codepoints for the following.
         final int separatorLength = separatorString.length();
         // TODO: should we check our saved separator against the actual contents of the text view?
@@ -1611,7 +1606,8 @@
         if (!TextUtils.isEmpty(committedWord)) {
             mDictionaryFacilitator.removeWordFromPersonalizedDicts(committedWordString);
         }
-        final String stringToCommit = originallyTypedWord + separatorString;
+        final String stringToCommit = originallyTypedWord +
+                (usePhantomSpace ? "" : separatorString);
         final SpannableString textToCommit = new SpannableString(stringToCommit);
         if (committedWord instanceof SpannableString) {
             final SpannableString committedWordWithSuggestionSpans = (SpannableString)committedWord;
@@ -1644,8 +1640,10 @@
                 }
             }
             // Add the suggestion list to the list of suggestions.
-            textToCommit.setSpan(new SuggestionSpan(inputTransaction.mSettingsValues.mLocale,
-                    suggestions.toArray(new String[suggestions.size()]), 0 /* flags */),
+            textToCommit.setSpan(new SuggestionSpan(mLatinIME /* context */,
+                    inputTransaction.mSettingsValues.mLocale,
+                    suggestions.toArray(new String[suggestions.size()]), 0 /* flags */,
+                    null /* notificationTargetClass */),
                     0 /* start */, lastCharIndex /* end */, 0 /* flags */);
         }
 
@@ -1663,6 +1661,9 @@
             } else {
                 mConnection.commitText(textToCommit, 1);
             }
+            if (usePhantomSpace) {
+                mSpaceState = SpaceState.PHANTOM;
+            }
         } else {
             // For languages without spaces, we revert the typed string but the cursor is flush
             // with the typed word, so we need to resume suggestions right away.
@@ -2186,10 +2187,7 @@
         }
         mConnection.tryFixLyingCursorPosition();
         if (tryResumeSuggestions) {
-            // This is triggered when starting input anew, so we want to include the resumed
-            // word in suggestions.
-            handler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
-                    true /* shouldDelay */);
+            handler.postResumeSuggestions(true /* shouldDelay */);
         }
         return true;
     }
diff --git a/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java b/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java
new file mode 100644
index 0000000..99e0e27
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java
@@ -0,0 +1,26 @@
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.NgramContext;
+
+public class NgramProperty {
+    public final WeightedString mTargetWord;
+    public final NgramContext mNgramContext;
+
+    public NgramProperty(final WeightedString targetWord, final NgramContext ngramContext) {
+        mTargetWord = targetWord;
+        mNgramContext = ngramContext;
+    }
+
+    @Override
+    public int hashCode() {
+        return mTargetWord.hashCode() ^ mNgramContext.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (!(o instanceof NgramProperty)) return false;
+        final NgramProperty n = (NgramProperty)o;
+        return mTargetWord.equals(n.mTargetWord) && mNgramContext.equals(n.mNgramContext);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index cd78e22..46705f9 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -18,6 +18,8 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
 import com.android.inputmethod.latin.utils.CombinedFormatUtils;
 import com.android.inputmethod.latin.utils.StringUtils;
 
@@ -33,16 +35,17 @@
     public final String mWord;
     public final ProbabilityInfo mProbabilityInfo;
     public final ArrayList<WeightedString> mShortcutTargets;
-    public final ArrayList<WeightedString> mBigrams;
+    public final ArrayList<NgramProperty> mNgrams;
     // TODO: Support mIsBeginningOfSentence.
     public final boolean mIsBeginningOfSentence;
     public final boolean mIsNotAWord;
     public final boolean mIsBlacklistEntry;
     public final boolean mHasShortcuts;
-    public final boolean mHasBigrams;
+    public final boolean mHasNgrams;
 
     private int mHashCode = 0;
 
+    // TODO: Support n-gram.
     @UsedForTesting
     public WordProperty(final String word, final ProbabilityInfo probabilityInfo,
             final ArrayList<WeightedString> shortcutTargets,
@@ -51,11 +54,17 @@
         mWord = word;
         mProbabilityInfo = probabilityInfo;
         mShortcutTargets = shortcutTargets;
-        mBigrams = bigrams;
+        mNgrams = new ArrayList<>();
+        final NgramContext ngramContext = new NgramContext(new WordInfo(mWord));
+        if (bigrams != null) {
+            for (final WeightedString bigramTarget : bigrams) {
+                mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
+            }
+        }
         mIsBeginningOfSentence = false;
         mIsNotAWord = isNotAWord;
         mIsBlacklistEntry = isBlacklistEntry;
-        mHasBigrams = bigrams != null && !bigrams.isEmpty();
+        mHasNgrams = bigrams != null && !bigrams.isEmpty();
         mHasShortcuts = shortcutTargets != null && !shortcutTargets.isEmpty();
     }
 
@@ -78,19 +87,24 @@
         mWord = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
         mProbabilityInfo = createProbabilityInfoFromArray(probabilityInfo);
         mShortcutTargets = new ArrayList<>();
-        mBigrams = new ArrayList<>();
+        mNgrams = new ArrayList<>();
         mIsBeginningOfSentence = isBeginningOfSentence;
         mIsNotAWord = isNotAWord;
         mIsBlacklistEntry = isBlacklisted;
         mHasShortcuts = hasShortcuts;
-        mHasBigrams = hasBigram;
+        mHasNgrams = hasBigram;
 
-        final int bigramTargetCount = bigramTargets.size();
-        for (int i = 0; i < bigramTargetCount; i++) {
-            final String bigramTargetString =
+        final int relatedNgramCount = bigramTargets.size();
+        final WordInfo currentWordInfo =
+                mIsBeginningOfSentence ? WordInfo.BEGINNING_OF_SENTENCE : new WordInfo(mWord);
+        final NgramContext ngramContext = new NgramContext(currentWordInfo);
+        for (int i = 0; i < relatedNgramCount; i++) {
+            final String ngramTargetString =
                     StringUtils.getStringFromNullTerminatedCodePointArray(bigramTargets.get(i));
-            mBigrams.add(new WeightedString(bigramTargetString,
-                    createProbabilityInfoFromArray(bigramProbabilityInfo.get(i))));
+            final WeightedString ngramTarget = new WeightedString(ngramTargetString,
+                    createProbabilityInfoFromArray(bigramProbabilityInfo.get(i)));
+            // TODO: Support n-gram.
+            mNgrams.add(new NgramProperty(ngramTarget, ngramContext));
         }
 
         final int shortcutTargetCount = shortcutTargets.size();
@@ -102,6 +116,17 @@
         }
     }
 
+    // TODO: Remove
+    public ArrayList<WeightedString> getBigrams() {
+        final ArrayList<WeightedString> bigrams = new ArrayList<>();
+        for (final NgramProperty ngram : mNgrams) {
+            if (ngram.mNgramContext.getPrevWordCount() == 1) {
+                bigrams.add(ngram.mTargetWord);
+            }
+        }
+        return bigrams;
+    }
+
     public int getProbability() {
         return mProbabilityInfo.mProbability;
     }
@@ -110,8 +135,8 @@
         return Arrays.hashCode(new Object[] {
                 word.mWord,
                 word.mProbabilityInfo,
-                word.mShortcutTargets.hashCode(),
-                word.mBigrams.hashCode(),
+                word.mShortcutTargets,
+                word.mNgrams,
                 word.mIsNotAWord,
                 word.mIsBlacklistEntry
         });
@@ -142,9 +167,9 @@
         if (!(o instanceof WordProperty)) return false;
         WordProperty w = (WordProperty)o;
         return mProbabilityInfo.equals(w.mProbabilityInfo) && mWord.equals(w.mWord)
-                && mShortcutTargets.equals(w.mShortcutTargets) && mBigrams.equals(w.mBigrams)
+                && mShortcutTargets.equals(w.mShortcutTargets) && mNgrams.equals(w.mNgrams)
                 && mIsNotAWord == w.mIsNotAWord && mIsBlacklistEntry == w.mIsBlacklistEntry
-                && mHasBigrams == w.mHasBigrams && mHasShortcuts && w.mHasBigrams;
+                && mHasNgrams == w.mHasNgrams && mHasShortcuts && w.mHasNgrams;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index a171fc3..83adb1c 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -32,6 +32,7 @@
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.RunInLocale;
+import com.android.inputmethod.latin.utils.StatsUtils;
 import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.util.Collections;
@@ -169,6 +170,7 @@
                 return;
             }
             loadSettings(mContext, mSettingsValues.mLocale, mSettingsValues.mInputAttributes);
+            StatsUtils.onLoadSettings(mSettingsValues);
         } finally {
             mSettingsValuesLock.unlock();
         }
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 1e8df89..839fce0 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -365,17 +365,21 @@
                     (PunctuationSuggestions)suggestedWords, stripView);
         }
 
+        final boolean shouldShowUiToAcceptTypedWord = Settings.getInstance().getCurrent()
+                .mShouldShowUiToAcceptTypedWord;
+        final int suggestionsCount = suggestedWords.size()
+                - (shouldShowUiToAcceptTypedWord ? /* typed word */ 1 : 0);
         final int startIndexOfMoreSuggestions = setupWordViewsAndReturnStartIndexOfMoreSuggestions(
                 suggestedWords, mSuggestionsCountInStrip);
         final TextView centerWordView = mWordViews.get(mCenterPositionInStrip);
         final int stripWidth = stripView.getWidth();
         final int centerWidth = getSuggestionWidth(mCenterPositionInStrip, stripWidth);
-        if (suggestedWords.size() == 1 || getTextScaleX(centerWordView.getText(), centerWidth,
+        if (suggestionsCount == 1 || getTextScaleX(centerWordView.getText(), centerWidth,
                 centerWordView.getPaint()) < MIN_TEXT_XSCALE) {
             // Layout only the most relevant suggested word at the center of the suggestion strip
             // by consolidating all slots in the strip.
             final int countInStrip = 1;
-            mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
+            mMoreSuggestionsAvailable = (suggestionsCount > countInStrip);
             layoutWord(mCenterPositionInStrip, stripWidth - mPadding);
             stripView.addView(centerWordView);
             setLayoutWeight(centerWordView, 1.0f, ViewGroup.LayoutParams.MATCH_PARENT);
@@ -387,7 +391,7 @@
         }
 
         final int countInStrip = mSuggestionsCountInStrip;
-        mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
+        mMoreSuggestionsAvailable = (suggestionsCount > countInStrip);
         int x = 0;
         for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
             if (positionInStrip != 0) {
diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
index 34f59e8..7e8e559 100644
--- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
@@ -67,7 +67,7 @@
             builder.append("," + BLACKLISTED_TAG + "=true");
         }
         builder.append("\n");
-        if (wordProperty.mShortcutTargets != null) {
+        if (wordProperty.mHasShortcuts) {
             for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
                 builder.append("  " + SHORTCUT_TAG + "=" + shortcutTarget.mWord);
                 builder.append(",");
@@ -75,8 +75,9 @@
                 builder.append("\n");
             }
         }
-        if (wordProperty.mBigrams != null) {
-            for (final WeightedString bigram : wordProperty.mBigrams) {
+        if (wordProperty.mHasNgrams) {
+            // TODO: Support ngram.
+            for (final WeightedString bigram : wordProperty.getBigrams()) {
                 builder.append("  " + BIGRAM_TAG + "=" + bigram.mWord);
                 builder.append(",");
                 builder.append(formatProbabilityInfo(bigram.mProbabilityInfo));
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 19aeb28..1e6baa5 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -373,7 +373,8 @@
     }
     // Use 1 for count to indicate the word has inputted.
     const UnigramProperty unigramProperty(isBeginningOfSentence, isNotAWord,
-            isBlacklisted, probability, timestamp, 0 /* level */, 1 /* count */, &shortcuts);
+            isBlacklisted, probability, HistoricalInfo(timestamp, 0 /* level */, 1 /* count */),
+            &shortcuts);
     return dictionary->addUnigramEntry(CodePointArrayView(codePoints, codePointCount),
             &unigramProperty);
 }
@@ -405,7 +406,7 @@
     env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
     // Use 1 for count to indicate the ngram has inputted.
     const NgramProperty ngramProperty(CodePointArrayView(wordCodePoints, wordLength).toVector(),
-            probability, timestamp, 0 /* level */, 1 /* count */);
+            probability, HistoricalInfo(timestamp, 0 /* level */, 1 /* count */));
     return dictionary->addNgramEntry(&prevWordsInfo, &ngramProperty);
 }
 
@@ -426,6 +427,19 @@
             CodePointArrayView(wordCodePoints, codePointCount));
 }
 
+static bool latinime_BinaryDictionary_updateCounter(JNIEnv *env, jclass clazz, jlong dict,
+        jobjectArray prevWordCodePointArrays, jbooleanArray isBeginningOfSentenceArray,
+        jintArray word, jboolean isValidWord, jint count, jint timestamp) {
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
+    if (!dictionary) {
+        return false;
+    }
+    jsize wordLength = env->GetArrayLength(word);
+    int wordCodePoints[wordLength];
+    env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
+    return false;
+}
+
 // Returns how many language model params are processed.
 static int latinime_BinaryDictionary_addMultipleDictionaryEntries(JNIEnv *env, jclass clazz,
         jlong dict, jobjectArray languageModelParams, jint startIndex) {
@@ -494,8 +508,8 @@
         }
         // Use 1 for count to indicate the word has inputted.
         const UnigramProperty unigramProperty(false /* isBeginningOfSentence */, isNotAWord,
-                isBlacklisted, unigramProbability, timestamp, 0 /* level */, 1 /* count */,
-                &shortcuts);
+                isBlacklisted, unigramProbability,
+                HistoricalInfo(timestamp, 0 /* level */, 1 /* count */), &shortcuts);
         dictionary->addUnigramEntry(CodePointArrayView(word1CodePoints, word1Length),
                 &unigramProperty);
         if (word0) {
@@ -503,7 +517,7 @@
             // Use 1 for count to indicate the bigram has inputted.
             const NgramProperty ngramProperty(
                     CodePointArrayView(word1CodePoints, word1Length).toVector(),
-                    bigramProbability, timestamp, 0 /* level */, 1 /* count */);
+                    bigramProbability, HistoricalInfo(timestamp, 0 /* level */, 1 /* count */));
             const PrevWordsInfo prevWordsInfo(word0CodePoints, word0Length,
                     false /* isBeginningOfSentence */);
             dictionary->addNgramEntry(&prevWordsInfo, &ngramProperty);
@@ -724,6 +738,11 @@
         reinterpret_cast<void *>(latinime_BinaryDictionary_removeNgramEntry)
     },
     {
+        const_cast<char *>("updateCounterNative"),
+        const_cast<char *>("(J[[I[Z[IZII)Z"),
+        reinterpret_cast<void *>(latinime_BinaryDictionary_updateCounter)
+    },
+    {
         const_cast<char *>("addMultipleDictionaryEntriesNative"),
         const_cast<char *>(
                 "(J[Lcom/android/inputmethod/latin/utils/LanguageModelParam;I)I"),
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h b/native/jni/src/suggest/core/dictionary/property/historical_info.h
similarity index 85%
rename from native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h
rename to native/jni/src/suggest/core/dictionary/property/historical_info.h
index 428ca86..5ed9ebf 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h
+++ b/native/jni/src/suggest/core/dictionary/property/historical_info.h
@@ -34,7 +34,7 @@
         return mTimestamp != NOT_A_TIMESTAMP;
     }
 
-    int getTimeStamp() const {
+    int getTimestamp() const {
         return mTimestamp;
     }
 
@@ -47,12 +47,12 @@
     }
 
  private:
-    // Copy constructor is public to use this class as a type of return value.
-    DISALLOW_ASSIGNMENT_OPERATOR(HistoricalInfo);
+    // Default copy constructor and assign operator are used for using in std::vector.
 
-    const int mTimestamp;
-    const int mLevel;
-    const int mCount;
+    // TODO: Make members const.
+    int mTimestamp;
+    int mLevel;
+    int mCount;
 };
 } // namespace latinime
 #endif /* LATINIME_HISTORICAL_INFO_H */
diff --git a/native/jni/src/suggest/core/dictionary/property/ngram_property.h b/native/jni/src/suggest/core/dictionary/property/ngram_property.h
index 5d822fa..49f683b 100644
--- a/native/jni/src/suggest/core/dictionary/property/ngram_property.h
+++ b/native/jni/src/suggest/core/dictionary/property/ngram_property.h
@@ -20,15 +20,16 @@
 #include <vector>
 
 #include "defines.h"
+#include "suggest/core/dictionary/property/historical_info.h"
 
 namespace latinime {
 
 class NgramProperty {
  public:
     NgramProperty(const std::vector<int> &&targetCodePoints, const int probability,
-            const int timestamp, const int level, const int count)
+            const HistoricalInfo &historicalInfo)
             : mTargetCodePoints(std::move(targetCodePoints)), mProbability(probability),
-              mTimestamp(timestamp), mLevel(level), mCount(count) {}
+              mHistoricalInfo(historicalInfo) {}
 
     const std::vector<int> *getTargetCodePoints() const {
         return &mTargetCodePoints;
@@ -38,16 +39,8 @@
         return mProbability;
     }
 
-    int getTimestamp() const {
-        return mTimestamp;
-    }
-
-    int getLevel() const {
-        return mLevel;
-    }
-
-    int getCount() const {
-        return mCount;
+    const HistoricalInfo getHistoricalInfo() const {
+        return mHistoricalInfo;
     }
 
  private:
@@ -57,9 +50,7 @@
     // TODO: Make members const.
     std::vector<int> mTargetCodePoints;
     int mProbability;
-    int mTimestamp;
-    int mLevel;
-    int mCount;
+    HistoricalInfo mHistoricalInfo;
 };
 } // namespace latinime
 #endif // LATINIME_NGRAM_PROPERTY_H
diff --git a/native/jni/src/suggest/core/dictionary/property/unigram_property.h b/native/jni/src/suggest/core/dictionary/property/unigram_property.h
index b7e7d66..4c61f96 100644
--- a/native/jni/src/suggest/core/dictionary/property/unigram_property.h
+++ b/native/jni/src/suggest/core/dictionary/property/unigram_property.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "defines.h"
+#include "suggest/core/dictionary/property/historical_info.h"
 
 namespace latinime {
 
@@ -50,15 +51,14 @@
 
     UnigramProperty()
             : mRepresentsBeginningOfSentence(false), mIsNotAWord(false), mIsBlacklisted(false),
-              mProbability(NOT_A_PROBABILITY), mTimestamp(NOT_A_TIMESTAMP), mLevel(0), mCount(0),
-              mShortcuts() {}
+              mProbability(NOT_A_PROBABILITY), mHistoricalInfo(), mShortcuts() {}
 
     UnigramProperty(const bool representsBeginningOfSentence, const bool isNotAWord,
-            const bool isBlacklisted, const int probability, const int timestamp, const int level,
-            const int count, const std::vector<ShortcutProperty> *const shortcuts)
+            const bool isBlacklisted, const int probability, const HistoricalInfo &historicalInfo,
+            const std::vector<ShortcutProperty> *const shortcuts)
             : mRepresentsBeginningOfSentence(representsBeginningOfSentence),
               mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted), mProbability(probability),
-              mTimestamp(timestamp), mLevel(level), mCount(count), mShortcuts(*shortcuts) {}
+              mHistoricalInfo(historicalInfo), mShortcuts(*shortcuts) {}
 
     bool representsBeginningOfSentence() const {
         return mRepresentsBeginningOfSentence;
@@ -85,16 +85,8 @@
         return mProbability;
     }
 
-    int getTimestamp() const {
-        return mTimestamp;
-    }
-
-    int getLevel() const {
-        return mLevel;
-    }
-
-    int getCount() const {
-        return mCount;
+    const HistoricalInfo getHistoricalInfo() const {
+        return mHistoricalInfo;
     }
 
     const std::vector<ShortcutProperty> &getShortcuts() const {
@@ -110,10 +102,7 @@
     bool mIsNotAWord;
     bool mIsBlacklisted;
     int mProbability;
-    // Historical information
-    int mTimestamp;
-    int mLevel;
-    int mCount;
+    HistoricalInfo mHistoricalInfo;
     std::vector<ShortcutProperty> mShortcuts;
 };
 } // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.cpp b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
index e3406fa..caac8fe 100644
--- a/native/jni/src/suggest/core/dictionary/property/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
@@ -17,6 +17,7 @@
 #include "suggest/core/dictionary/property/word_property.h"
 
 #include "utils/jni_data_utils.h"
+#include "suggest/core/dictionary/property/historical_info.h"
 
 namespace latinime {
 
@@ -31,8 +32,9 @@
             !mNgrams.empty(), mUnigramProperty.hasShortcuts(),
             mUnigramProperty.representsBeginningOfSentence()};
     env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
-    int probabilityInfo[] = {mUnigramProperty.getProbability(), mUnigramProperty.getTimestamp(),
-            mUnigramProperty.getLevel(), mUnigramProperty.getCount()};
+    const HistoricalInfo &historicalInfo = mUnigramProperty.getHistoricalInfo();
+    int probabilityInfo[] = {mUnigramProperty.getProbability(), historicalInfo.getTimestamp(),
+            historicalInfo.getLevel(), historicalInfo.getCount()};
     env->SetIntArrayRegion(outProbabilityInfo, 0 /* start */, NELEMS(probabilityInfo),
             probabilityInfo);
 
@@ -51,10 +53,10 @@
                 false /* needsNullTermination */);
         env->CallBooleanMethod(outBigramTargets, addMethodId, bigramWord1CodePointArray);
         env->DeleteLocalRef(bigramWord1CodePointArray);
-
+        const HistoricalInfo &ngramHistoricalInfo = ngramProperty.getHistoricalInfo();
         int bigramProbabilityInfo[] = {ngramProperty.getProbability(),
-                ngramProperty.getTimestamp(), ngramProperty.getLevel(),
-                ngramProperty.getCount()};
+                ngramHistoricalInfo.getTimestamp(), ngramHistoricalInfo.getLevel(),
+                ngramHistoricalInfo.getCount()};
         jintArray bigramProbabilityInfoArray = env->NewIntArray(NELEMS(bigramProbabilityInfo));
         env->SetIntArrayRegion(bigramProbabilityInfoArray, 0 /* start */,
                 NELEMS(bigramProbabilityInfo), bigramProbabilityInfo);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp
index c639770..bc0f47f 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp
@@ -267,8 +267,7 @@
         const NgramProperty *const ngramProperty) const {
     // TODO: Consolidate historical info and probability.
     if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(ngramProperty->getTimestamp(),
-                ngramProperty->getLevel(), ngramProperty->getCount());
+        const HistoricalInfo &historicalInfoForUpdate = ngramProperty->getHistoricalInfo();
         const HistoricalInfo updatedHistoricalInfo =
                 ForgettingCurveUtils::createUpdatedHistoricalInfo(
                         originalBigramEntry->getHistoricalInfo(), ngramProperty->getProbability(),
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.cpp
index e2dd93c..9e1adff 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.cpp
@@ -83,10 +83,10 @@
     }
     if (mHasHistoricalInfo) {
         const HistoricalInfo *const historicalInfo = bigramEntryToWrite->getHistoricalInfo();
-        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
+        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getTimestamp(),
                 Ver4DictConstants::TIME_STAMP_FIELD_SIZE, entryWritingPos)) {
             AKLOGE("Cannot write bigram timestamps. pos: %d, timestamp: %d", *entryWritingPos,
-                    historicalInfo->getTimeStamp());
+                    historicalInfo->getTimestamp());
             return false;
         }
         if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getLevel(),
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h
index 40968b4..480095a 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h
@@ -25,8 +25,8 @@
 #define LATINIME_BACKWARD_V402_BIGRAM_ENTRY_H
 
 #include "defines.h"
+#include "suggest/core/dictionary/property/historical_info.h"
 #include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
 
 namespace latinime {
 namespace backward {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.cpp
index c671647..4a740d4 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.cpp
@@ -147,7 +147,7 @@
     }
     if (mHasHistoricalInfo) {
         const HistoricalInfo *const historicalInfo = probabilityEntry->getHistoricalInfo();
-        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
+        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getTimestamp(),
                 Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &writingPos)) {
             AKLOGE("Cannot write timestamp in probability dict content. pos: %d", writingPos);
             return false;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h
index 8ccfa33..4111a49 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h
@@ -25,8 +25,8 @@
 #define LATINIME_BACKWARD_V402_PROBABILITY_ENTRY_H
 
 #include "defines.h"
+#include "suggest/core/dictionary/property/historical_info.h"
 #include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
 
 namespace latinime {
 namespace backward {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
index 6827c3e..8d16974 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
@@ -396,8 +396,7 @@
         const UnigramProperty *const unigramProperty) const {
     // TODO: Consolidate historical info and probability.
     if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(unigramProperty->getTimestamp(),
-                unigramProperty->getLevel(), unigramProperty->getCount());
+        const HistoricalInfo &historicalInfoForUpdate = unigramProperty->getHistoricalInfo();
         const HistoricalInfo updatedHistoricalInfo =
                 ForgettingCurveUtils::createUpdatedHistoricalInfo(
                         originalProbabilityEntry->getHistoricalInfo(),
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
index 9631cf1..40e393c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
@@ -343,7 +343,7 @@
             const UnigramProperty beginningOfSentenceUnigramProperty(
                     true /* representsBeginningOfSentence */, true /* isNotAWord */,
                     false /* isBlacklisted */, MAX_PROBABILITY /* probability */,
-                    NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
+                    HistoricalInfo(), &shortcuts);
             if (!addUnigramEntry(prevWordsInfo->getNthPrevWordCodePoints(1 /* n */),
                     &beginningOfSentenceUnigramProperty)) {
                 AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
@@ -528,8 +528,7 @@
                     bigramEntry.getProbability();
             ngrams.emplace_back(
                     CodePointArrayView(bigramWord1CodePoints, codePointCount).toVector(),
-                    probability, historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-                    historicalInfo->getCount());
+                    probability, *historicalInfo);
         }
     }
     // Fetch shortcut information.
@@ -552,8 +551,7 @@
     }
     const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
             ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
-            historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-            historicalInfo->getCount(), &shortcuts);
+            *historicalInfo, &shortcuts);
     return WordProperty(wordCodePoints.toVector(), &unigramProperty, &ngrams);
 }
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
index 3fb4caa..2887dc6 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
@@ -216,7 +216,7 @@
                         probabilityEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
                 probabilityEntry.getProbability();
         priorityQueue.push(DictProbability(terminalPos, probability,
-                probabilityEntry.getHistoricalInfo()->getTimeStamp()));
+                probabilityEntry.getHistoricalInfo()->getTimestamp()));
     }
 
     // Delete unigrams.
@@ -263,7 +263,7 @@
                             bigramEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
                     bigramEntry.getProbability();
             priorityQueue.push(DictProbability(entryPos, probability,
-                    bigramEntry.getHistoricalInfo()->getTimeStamp()));
+                    bigramEntry.getHistoricalInfo()->getTimestamp()));
         }
     }
 
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 49095d0..7800758 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
@@ -452,7 +452,7 @@
             const int probability = getProbability(word1Probability, bigramsIt.getProbability());
             ngrams.emplace_back(
                     CodePointArrayView(bigramWord1CodePoints, word1CodePointCount).toVector(),
-                    probability, NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */);
+                    probability, HistoricalInfo());
         }
     }
     // Fetch shortcut information.
@@ -477,7 +477,7 @@
     }
     const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
             ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
-            NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
+            HistoricalInfo(), &shortcuts);
     return WordProperty(wordCodePoints.toVector(), &unigramProperty, &ngrams);
 }
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
index 1392302..956dabb 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
@@ -296,7 +296,7 @@
                 ForgettingCurveUtils::decodeProbability(probabilityEntry.getHistoricalInfo(),
                         headerPolicy) : probabilityEntry.getProbability();
         outEntryInfo->emplace_back(probability,
-                probabilityEntry.getHistoricalInfo()->getTimeStamp(),
+                probabilityEntry.getHistoricalInfo()->getTimestamp(),
                 entry.key(), targetLevel, prevWordIds->data());
     }
     return true;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
index fd52e57..fa14156 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
@@ -21,10 +21,10 @@
 #include <cstdint>
 
 #include "defines.h"
+#include "suggest/core/dictionary/property/historical_info.h"
 #include "suggest/core/dictionary/property/ngram_property.h"
 #include "suggest/core/dictionary/property/unigram_property.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
 
 namespace latinime {
 
@@ -53,15 +53,13 @@
                     unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
                     unigramProperty->isPossiblyOffensive())),
               mProbability(unigramProperty->getProbability()),
-              mHistoricalInfo(unigramProperty->getTimestamp(), unigramProperty->getLevel(),
-                      unigramProperty->getCount()) {}
+              mHistoricalInfo(unigramProperty->getHistoricalInfo()) {}
 
     // Create from ngram property.
     // TODO: Set flags.
     ProbabilityEntry(const NgramProperty *const ngramProperty)
             : mFlags(0), mProbability(ngramProperty->getProbability()),
-              mHistoricalInfo(ngramProperty->getTimestamp(), ngramProperty->getLevel(),
-                      ngramProperty->getCount()) {}
+              mHistoricalInfo(ngramProperty->getHistoricalInfo()) {}
 
     bool isValid() const {
         return (mFlags & Ver4DictConstants::FLAG_NOT_A_VALID_ENTRY) == 0;
@@ -103,7 +101,7 @@
         uint64_t encodedEntry = static_cast<uint64_t>(mFlags);
         if (hasHistoricalInfo) {
             encodedEntry = (encodedEntry << (Ver4DictConstants::TIME_STAMP_FIELD_SIZE * CHAR_BIT))
-                    ^ static_cast<uint64_t>(mHistoricalInfo.getTimeStamp());
+                    ^ static_cast<uint64_t>(mHistoricalInfo.getTimestamp());
             encodedEntry = (encodedEntry << (Ver4DictConstants::WORD_LEVEL_FIELD_SIZE * CHAR_BIT))
                     ^ static_cast<uint64_t>(mHistoricalInfo.getLevel());
             encodedEntry = (encodedEntry << (Ver4DictConstants::WORD_COUNT_FIELD_SIZE * CHAR_BIT))
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 d46acf5..0badabf 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
@@ -302,7 +302,7 @@
         const UnigramProperty beginningOfSentenceUnigramProperty(
                 true /* representsBeginningOfSentence */, true /* isNotAWord */,
                 false /* isBlacklisted */, MAX_PROBABILITY /* probability */,
-                NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
+                HistoricalInfo(), &shortcuts);
         if (!addUnigramEntry(prevWordsInfo->getNthPrevWordCodePoints(1 /* n */),
                 &beginningOfSentenceUnigramProperty)) {
             AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
@@ -464,8 +464,7 @@
                 ForgettingCurveUtils::decodeProbability(historicalInfo, mHeaderPolicy) :
                 probabilityEntry.getProbability();
         ngrams.emplace_back(CodePointArrayView(bigramWord1CodePoints, codePointCount).toVector(),
-                probability, historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-                historicalInfo->getCount());
+                probability, *historicalInfo);
     }
     // Fetch shortcut information.
     std::vector<UnigramProperty::ShortcutProperty> shortcuts;
@@ -487,8 +486,7 @@
     }
     const UnigramProperty unigramProperty(probabilityEntry.representsBeginningOfSentence(),
             probabilityEntry.isNotAWord(), probabilityEntry.isBlacklisted(),
-            probabilityEntry.getProbability(), historicalInfo->getTimeStamp(),
-            historicalInfo->getLevel(), historicalInfo->getCount(), &shortcuts);
+            probabilityEntry.getProbability(), *historicalInfo, &shortcuts);
     return WordProperty(wordCodePoints.toVector(), &unigramProperty, &ngrams);
 }
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
index fed0ae7..af4bc18 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
@@ -43,7 +43,7 @@
 /* static */ const HistoricalInfo ForgettingCurveUtils::createUpdatedHistoricalInfo(
         const HistoricalInfo *const originalHistoricalInfo, const int newProbability,
         const HistoricalInfo *const newHistoricalInfo, const HeaderPolicy *const headerPolicy) {
-    const int timestamp = newHistoricalInfo->getTimeStamp();
+    const int timestamp = newHistoricalInfo->getTimestamp();
     if (newProbability != NOT_A_PROBABILITY && originalHistoricalInfo->getLevel() == 0) {
         // Add entry as a valid word.
         const int level = clampToVisibleEntryLevelRange(newHistoricalInfo->getLevel());
@@ -78,7 +78,7 @@
 
 /* static */ int ForgettingCurveUtils::decodeProbability(
         const HistoricalInfo *const historicalInfo, const HeaderPolicy *const headerPolicy) {
-    const int elapsedTimeStepCount = getElapsedTimeStepCount(historicalInfo->getTimeStamp(),
+    const int elapsedTimeStepCount = getElapsedTimeStepCount(historicalInfo->getTimestamp(),
             headerPolicy->getForgettingCurveDurationToLevelDown());
     return sProbabilityTable.getProbability(
             headerPolicy->getForgettingCurveProbabilityValuesTableId(),
@@ -102,7 +102,7 @@
 /* static */ bool ForgettingCurveUtils::needsToKeep(const HistoricalInfo *const historicalInfo,
         const HeaderPolicy *const headerPolicy) {
     return historicalInfo->getLevel() > 0
-            || getElapsedTimeStepCount(historicalInfo->getTimeStamp(),
+            || getElapsedTimeStepCount(historicalInfo->getTimestamp(),
                     headerPolicy->getForgettingCurveDurationToLevelDown())
                             < DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD;
 }
@@ -110,12 +110,12 @@
 /* static */ const HistoricalInfo ForgettingCurveUtils::createHistoricalInfoToSave(
         const HistoricalInfo *const originalHistoricalInfo,
         const HeaderPolicy *const headerPolicy) {
-    if (originalHistoricalInfo->getTimeStamp() == NOT_A_TIMESTAMP) {
+    if (originalHistoricalInfo->getTimestamp() == NOT_A_TIMESTAMP) {
         return HistoricalInfo();
     }
     const int durationToLevelDownInSeconds = headerPolicy->getForgettingCurveDurationToLevelDown();
     const int elapsedTimeStep = getElapsedTimeStepCount(
-            originalHistoricalInfo->getTimeStamp(), durationToLevelDownInSeconds);
+            originalHistoricalInfo->getTimestamp(), durationToLevelDownInSeconds);
     if (elapsedTimeStep <= MAX_ELAPSED_TIME_STEP_COUNT) {
         // No need to update historical info.
         return *originalHistoricalInfo;
@@ -124,7 +124,7 @@
     const int maxLevelDownAmonut = elapsedTimeStep / (MAX_ELAPSED_TIME_STEP_COUNT + 1);
     const int levelDownAmount = (maxLevelDownAmonut >= originalHistoricalInfo->getLevel()) ?
             originalHistoricalInfo->getLevel() : maxLevelDownAmonut;
-    const int adjustedTimestampInSeconds = originalHistoricalInfo->getTimeStamp() +
+    const int adjustedTimestampInSeconds = originalHistoricalInfo->getTimestamp() +
             levelDownAmount * durationToLevelDownInSeconds;
     return HistoricalInfo(adjustedTimestampInSeconds,
             originalHistoricalInfo->getLevel() - levelDownAmount, 0 /* count */);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
index 313eb6b..10abb40 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
@@ -20,7 +20,7 @@
 #include <vector>
 
 #include "defines.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
+#include "suggest/core/dictionary/property/historical_info.h"
 
 namespace latinime {
 
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
index daa32c3..4469dc7 100644
--- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
+++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
@@ -60,7 +60,7 @@
     languageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry);
     const ProbabilityEntry entry = languageModelDictContent.getProbabilityEntry(wordId);
     EXPECT_EQ(flag, entry.getFlags());
-    EXPECT_EQ(timestamp, entry.getHistoricalInfo()->getTimeStamp());
+    EXPECT_EQ(timestamp, entry.getHistoricalInfo()->getTimestamp());
     EXPECT_EQ(level, entry.getHistoricalInfo()->getLevel());
     EXPECT_EQ(count, entry.getHistoricalInfo()->getCount());
 
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp
index f0494f3..260b347 100644
--- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp
+++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp
@@ -51,7 +51,7 @@
             ProbabilityEntry::decode(encodedEntry, true /* hasHistoricalInfo */);
 
     EXPECT_EQ(flag, decodedEntry.getFlags());
-    EXPECT_EQ(timestamp, decodedEntry.getHistoricalInfo()->getTimeStamp());
+    EXPECT_EQ(timestamp, decodedEntry.getHistoricalInfo()->getTimestamp());
     EXPECT_EQ(level, decodedEntry.getHistoricalInfo()->getLevel());
     EXPECT_EQ(count, decodedEntry.getHistoricalInfo()->getCount());
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
index 25bac9d..dc95315 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
@@ -25,8 +25,8 @@
 
 @SmallTest
 public class KeyboardLayoutSetSubtypesCountTests extends KeyboardLayoutSetTestsBase {
-    private static final int NUMBER_OF_SUBTYPES = 81;
-    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 49;
+    private static final int NUMBER_OF_SUBTYPES = 85;
+    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 50;
     private static final int NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES = 2;
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java b/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java
index 2101ddf..24852a0 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java
@@ -18,9 +18,6 @@
 
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
 
 /**
  * The Bengali keyboard.
@@ -35,32 +32,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class BengaliCustomizer extends LayoutCustomizer {
-        public BengaliCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey getAlphabetKey() { return BENGALI_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey[] getOtherCurrencyKeys() {
-            return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
-        }
-
-        @Override
-        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) { return EMPTY_KEYS; }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        // U+0995: "क" BENGALI LETTER KA
-        // U+0996: "ख" BENGALI LETTER KHA
-        // U+0997: "ग" BENGALI LETTER GA
-        private static final ExpectedKey BENGALI_ALPHABET_KEY = key(
-                "\u0995\u0996\u0997", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/BengaliAkkhor.java b/tests/src/com/android/inputmethod/keyboard/layout/BengaliAkkhor.java
new file mode 100644
index 0000000..4dc16cf
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/BengaliAkkhor.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout;
+
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+/**
+ * The Bengali Akkhor keyboard.
+ */
+public final class BengaliAkkhor extends LayoutBase {
+    private static final String LAYOUT_NAME = "bengali_akkhor";
+
+    public BengaliAkkhor(final LayoutCustomizer customizer) {
+        super(customizer, Symbols.class, SymbolsShifted.class);
+    }
+
+    @Override
+    public String getName() { return LAYOUT_NAME; }
+
+    @Override
+    ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
+
+    @Override
+    ExpectedKey[][] getCommonAlphabetShiftLayout(boolean isPhone, final int elementId) {
+        if (elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
+            return getCommonAlphabetLayout(isPhone);
+        }
+        return ALPHABET_SHIFTED_COMMON;
+    }
+
+    private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
+            .setKeysOfRow(1,
+                    // U+09A7: "ধ" BENGALI LETTER DHA
+                    // U+09E7: "১" BENGALI DIGIT ONE
+                    // U+09A7/U+09CD/U+09AC:
+                    //     "ধ্ব্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A7/U+09CD/U+09AF:
+                    //     "ধ্য্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09A7/U+09CD/U+09B0:
+                    //     "ধ্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u09A7", joinMoreKeys("\u09E7", "\u09A7\u09CD\u09AC", "\u09A7\u09CD\u09AF",
+                            "\u09A7\u09CD\u09B0")),
+                    // U+09A5: "থ" BENGALI LETTER THA
+                    // U+09E8: "২" BENGALI DIGIT TWO
+                    // U+09A5/U+09CD/U+09AF:
+                    //     "থ্য" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09A5/U+09CD/U+09B0:
+                    //     "থ্র" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u09A5", joinMoreKeys("\u09E8", "\u09A5\u09CD\u09AF",
+                            "\u09A5\u09CD\u09B0")),
+                    // U+09C7: "ে" BENGALI VOWEL SIGN E
+                    // U+09E9: "৩" BENGALI DIGIT THREE
+                    // U+098F: "এ" BENGALI LETTER E
+                    key("\u09C7", joinMoreKeys("\u09E9", "\u098F")),
+                    // U+09B0: "র" BENGALI LETTER RA
+                    // U+09EA: "৪" BENGALI DIGIT FOUR
+                    key("\u09B0", joinMoreKeys("\u09EA")),
+                    // U+09A4: "ত" BENGALI LETTER TA
+                    // U+09EB: "৫" BENGALI DIGIT FIVE
+                    // U+09CE: "ৎ" BENGALI LETTER KHANDA TA
+                    // U+09A4/U+09CD/U+09A4:
+                    //     "ত্ত" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09A4/U+09CD/U+09A8:
+                    //     "ত্ন" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09A4/U+09CD/U+09AC:
+                    //     "ত্ব" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A4/U+09CD/U+09AE:
+                    //     "ত্ম" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    key("\u09A4", joinMoreKeys("\u09EB", "\u09CE", "\u09A4\u09CD\u09A4",
+                            "\u09A4\u09CD\u09A8", "\u09A4\u09CD\u09AC", "\u09A4\u09CD\u09AE")),
+                    // U+09DF: "য়" BENGALI LETTER YYA
+                    // U+09EC: "৬" BENGALI DIGIT SIX
+                    key("\u09DF", joinMoreKeys("\u09EC")),
+                    // U+09C1: "ু" BENGALI VOWEL SIGN U
+                    // U+09ED: "৭" BENGALI DIGIT SEVEN
+                    // U+0989: "উ" BENGALI LETTER U
+                    key("\u09C1", joinMoreKeys("\u09ED", "\u0989")),
+                    // U+09BF: "ি" BENGALI VOWEL SIGN I
+                    // U+09EE: "৮" BENGALI DIGIT EIGHT
+                    // U+0987: "ই BENGALI LETTER I
+                    key("\u09Bf", joinMoreKeys("\u09EE", "\u0987")),
+                    // U+09CB: "ো" BENGALI VOWEL SIGN O
+                    // U+09EF: "৯" BENGALI DIGIT NINE
+                    // U+0993: "ও" BENGALI LETTER O
+                    key("\u09CB", joinMoreKeys("\u09EF", "\u0993")),
+                    // U+09AA: "প" BENGALI LETTER PA
+                    // U+09E6: "০" BENGALI DIGIT ZERO
+                    // U+09AA/U+09CD/U+09A4:
+                    //     "প্ত" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09AA/U+09CD/U+09A8:
+                    //     "প্ন" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09AA/U+09CD/U+09AA:
+                    //     "প্প" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09AA/U+09CD/U+09AF:
+                    //     "প্য" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09AA/U+09CD/U+09B0:
+                    //     "প্র" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AA/U+09CD/U+09B2:
+                    //     "প্ল" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    // U+09AA/U+09CD/U+09B8:
+                    //     "প্স" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                    key("\u09AA", joinMoreKeys("\u09E6", "\u09AA\u09CD\u09A4", "\u09AA\u09CD\u09A8",
+                            "\u09AA\u09CD\u09AA", "\u09AA\u09CD\u09AF", "\u09AA\u09CD\u09B0",
+                            "\u09AA\u09CD\u09B2", "\u09AA\u09CD\u09B8")),
+                    // U+0986: "আ" BENGALI LETTER AA
+                    key("\u0986"))
+            .setKeysOfRow(2,
+                    // U+09BE: "া BENGALI VOWEL SIGN AA
+                    // U+0986: "আ" BENGALI LETTER AA
+                    key("\u09BE", moreKey("\u0986")),
+                    // U+09B8: "স" BENGALI LETTER SA
+                    // U+09B8/U+09CD/U+09AC:
+                    //     "স্ব" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B8/U+09CD/U+09A4:
+                    //     "স্ত" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09B8/U+09CD/U+099F:
+                    //     "স্ট" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09B8/U+09CD/U+0995:
+                    //     "স্ক" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+09B8/U+09CD/U+09AA:
+                    //     "স্প" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    key("\u09B8", joinMoreKeys("\u09B8\u09CD\u09AC", "\u09B8\u09CD\u09A4",
+                            "\u09B8\u09CD\u099F", "\u09B8\u09CD\u0995", "\u09B8\u09CD\u09AA")),
+                    // U+09A6: "দ" BENGALI LETTER DA
+                    // U+09A6/U+09CD/U+09A6:
+                    //     "দ্দ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09A6/U+09CD/U+09A7:
+                    //     "দ্ধ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09A6/U+09CD/U+09AC:
+                    //     "দ্ব" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A6/U+09CD/U+09AD:
+                    //     "দ্ভ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                    // U+09A6/U+09CD/U+09AE:
+                    //     "দ্ম" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09A6/U+09CD/U+09AF:
+                    //     "দ্য" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09A6/U+09CD/U+09B0:
+                    //     "দ্র" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u09A6", joinMoreKeys("\u09A6\u09CD\u09A6", "\u09A6\u09CD\u09A7",
+                            "\u09A6\u09CD\u09AC", "\u09A6\u09CD\u09AD", "\u09A6\u09CD\u09AE",
+                            "\u09A6\u09CD\u09AF", "\u09A6\u09CD\u09B0")),
+                    // U+09C3: "ৃ" BENGALI VOWEL SIGN VOCALIC R
+                    // U+098B: "ঋ" BENGALI LETTER VOCALIC R
+                    key("\u09C3", moreKey("\u098B")),
+                    // U+0997: "গ" BENGALI LETTER GA
+                    // U+0997/U+09CD/U+09A7:
+                    //     "গ্ধ" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER DH A
+                    // U+0997/U+09CD/U+09B0:
+                    //     "গ্র" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+0997/U+09CD/U+09B2:
+                    //     "গ্ল" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    // U+0997/U+09CD/U+09A8:
+                    //     "গ্ন" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    key("\u0997", joinMoreKeys("\u0997\u09CD\u09A7", "\u0997\u09CD\u09B0",
+                            "\u0997\u09CD\u09B2", "\u0997\u09CD\u09A8")),
+                    // U+09CD: "্" BENGALI SIGN VIRAMA
+                    key("\u09CD"),
+                    // U+099C: "জ" BENGALI LETTER JA
+                    // U+099C/U+09CD/U+099E:
+                    //     "জ্ঞ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER NYA
+                    // U+099C/U+09CD/U+099C:
+                    //     "জ্জ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                    // U+099C/U+09CD/U+09AF:
+                    //     "জ্ব" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+099C/U+09CD/U+09AC:
+                    //     "জ্য" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+099C/U+09CD/U+09B0:
+                    //     "জ্র" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u099C", joinMoreKeys("\u099C\u09CD\u099E", "\u099C\u09CD\u099C",
+                            "\u099C\u09CD\u09AF", "\u099C\u09CD\u09AC", "\u099C\u09CD\u09B0")),
+                    // U+0995: "ক" BENGALI LETTER KA
+                    // U+0995/U+09CD/U+09B7:
+                    //     "ক্ষ" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SSA
+                    // U+0995/U+09CD/U+0995:
+                    //     "ক্ক" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+0995/U+09CD/U+099F:
+                    //     "ক্ট" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+0995/U+09CD/U+09A4:
+                    //     "ক্ত" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+0995/U+09CD/U+09B0:
+                    //     "ক্র" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+0995/U+09CD/U+09B8:
+                    //     "ক্স" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                    // U+0995/U+09CD/U+09B2:
+                    //     "ক্ল" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u0995", joinMoreKeys("\u0995\u09CD\u09B7", "\u0995\u09CD\u0995",
+                            "\u0995\u09CD\u099F", "\u0995\u09CD\u09A4", "\u0995\u09CD\u09B0",
+                            "\u0995\u09CD\u09B8", "\u0995\u09CD\u09B2")),
+                    // U+09B2: "ল" BENGALI LETTER LA
+                    // U+09B2/U+09CD/U+0995:
+                    //     "ল্ক" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+09B2/U+09CD/U+0997:
+                    //     "ল্গ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER GA
+                    // U+09B2/U+09CD/U+099F:
+                    //     "ল্ট" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09B2/U+09CD/U+09A1:
+                    //     "ল্ড" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    // U+09B2/U+09CD/U+09A4:
+                    //     "ল্ত" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09B2/U+09CD/U+09A6:
+                    //     "ল্দ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09B2/U+09CD/U+09A7:
+                    //     "ল্ধ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09B2/U+09CD/U+09AA:
+                    //     "ল্প" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09B2/U+09CD/U+09AB:
+                    //     "ল্ফ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                    // U+09B2/U+09CD/U+09AC:
+                    //     "ল্ব" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B2/U+09CD/U+09AE:
+                    //     "ল্ম" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09B2/U+09CD/U+09B2:
+                    //     "ল্ল" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09B2", joinMoreKeys("\u09B2\u09CD\u0995", "\u09B2\u09CD\u0997",
+                            "\u09B2\u09CD\u099F", "\u09B2\u09CD\u09A1", "\u09B2\u09CD\u09A4",
+                            "\u09B2\u09CD\u09A6", "\u09B2\u09CD\u09A7", "\u09B2\u09CD\u09AA",
+                            "\u09B2\u09CD\u09AB", "\u09B2\u09CD\u09AC", "\u09B2\u09CD\u09AE",
+                            "\u09B2\u09CD\u09B2")),
+                    // U+0987: "ই" BENGALI LETTER I
+                    key("\u0987"),
+                    // U+0989: "উ" BENGALI LETTER U
+                    key("\u0989"))
+            .setKeysOfRow(3,
+                    // U+09AF: "য" BENGALI LETTER YA
+                    // U+09CD/U+09AF: "্য" BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    key("\u09AF", moreKey("\u09CD\u09AF")),
+                    // U+09B7: "ষ" BENGALI LETTER SSA
+                    // U+09B7/U+09CD/U+0995:
+                    //     "ষ্ক" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+09B7/U+09CD/U+099F:
+                    //     "ষ্ট" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09B7/U+09CD/U+09A0:
+                    //     "ষ্ঠ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTHA
+                    // U+09B7/U+09CD/U+09A3:
+                    //     "ষ্ণ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                    // U+09B7/U+09CD/U+09AA:
+                    //     "ষ্প" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09B7/U+09CD/U+09AB:
+                    //     "ষ্ফ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                    // U+09B7/U+09CD/U+09AE:
+                    //     "ষ্ম" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    key("\u09B7", joinMoreKeys("\u09B7\u09CD\u0995", "\u09B7\u09CD\u099F",
+                            "\u09B7\u09CD\u09A0", "\u09B7\u09CD\u09A3", "\u09B7\u09CD\u09AA",
+                            "\u09B7\u09CD\u09AB", "\u09B7\u09CD\u09AE")),
+                    // U+099A: "চ" BENGALI LETTER CA
+                    // U+099A/U+09CD/U+099A:
+                    //     "চ্চ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                    // U+099A/U+09CD/U+099B:
+                    //     "চ্ছ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                    key("\u099A", joinMoreKeys("\u099A\u09CD\u099A", "\u099A\u09CD\u099B")),
+                    // U+09AD: "ভ" BENGALI LETTER BHA
+                    // U+09AD/U+09CD/U+09AF:
+                    //     "ভ্" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09AD/U+09CD/U+09B0:
+                    //     "ভ্র" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AD/U+09CD/U+09B2:
+                    //     "ভ্ল" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09AD", joinMoreKeys("\u09AD\u09CD\u09AF", "\u09AD\u09CD\u09B0",
+                            "\u09AD\u09CD\u09B2")),
+                    // U+09AC: "ব" BENGALI LETTER BA
+                    // U+09CD/U+09AC: "্ব" BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09AC/U+09CD/U+09B0:
+                    //     "ব্র" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AC/U+09CD/U+099C:
+                    //     "ব্জ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                    // U+09AC/U+09CD/U+09A6:
+                    //     "ব্দ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09AC/U+09CD/U+09A7:
+                    //     "ব্ধ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09AC/U+09CD/U+09AC:
+                    //     "ব্ব" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09AC/U+09CD/U+09B2:
+                    //     "ব্ল" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    // U+09F1: "ৱ" BENGALI LETTER RA WITH MIDDLE DIAGONAL
+                    // U+09F0: "ৰ" BENGALI LETTER RA WITH LOWER DIAGONAL
+                    key("\u09AC", joinMoreKeys("\u09CD\u09AC", "\u09AC\u09CD\u09B0",
+                            "\u09AC\u09CD\u099C", "\u09AC\u09CD\u09A6", "\u09AC\u09CD\u09A7",
+                            "\u09AC\u09CD\u09AC", "\u09AC\u09CD\u09B2", "\u09F1", "\u09F0")),
+                    // U+09A8: "ন" BENGALI LETTER NA
+                    // U+09A8/U+09CD/U+09A4:
+                    //     "ন্ত" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09A8/U+09CD/U+09A5:
+                    //     "ন্থ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER THA
+                    // U+09A8/U+09CD/U+099F:
+                    //     "ন্ট" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09A8/U+09CD/U+09A6:
+                    //     "ন্দ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09A8/U+09CD/U+09A7:
+                    //     "ন্ধ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09A8/U+09CD/U+09A1:
+                    //     "ন্ড" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    // U+09A8/U+09CD/U+09A8:
+                    //     "ন্ন" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09A8/U+09CD/U+09AC:
+                    //     "ন্ব" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A8/U+09CD/U+09AE:
+                    //     "ন্ম" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09A8/U+09CD/U+09B8:
+                    //     "ন্স" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                    key("\u09A8", joinMoreKeys("\u09A8\u09CD\u09A4", "\u09A8\u09CD\u09A5",
+                            "\u09A8\u09CD\u099F", "\u09A8\u09CD\u09A6", "\u09A8\u09CD\u09A7",
+                            "\u09A8\u09CD\u09A1", "\u09A8\u09CD\u09A8", "\u09A8\u09CD\u09AC",
+                            "\u09A8\u09CD\u09AE", "\u09A8\u09CD\u09B8")),
+                    // U+09AE: "ম" BENGALI LETTER MA
+                    // U+09AE/U+09CD/U+09A8:
+                    //     "ম্ন" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09AE/U+09CD/U+09AA:
+                    //     "ম্প" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09AE/U+09CD/U+09AC:
+                    //     "ম্ব" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09AE/U+09CD/U+09AD:
+                    //     "ম্ভ" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                    // U+09AE/U+09CD/U+09AE:
+                    //     "ম্ম" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09AE/U+09CD/U+09B0:
+                    //     "ম্র" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AE/U+09CD/U+09B2:
+                    //     "ম্ল" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09AE", joinMoreKeys("\u09AE\u09CD\u09A8", "\u09AE\u09CD\u09AA",
+                            "\u09AE\u09CD\u09AC", "\u09AE\u09CD\u09AD", "\u09AE\u09CD\u09AE",
+                            "\u09AE\u09CD\u09B0", "\u09AE\u09CD\u09B2")),
+                    // U+098F: "এ" BENGALI LETTER E
+                    key("\u098F"),
+                    // U+0993: "ও" BENGALI LETTER O
+                    key("\u0993"))
+            .build();
+
+    private static final ExpectedKey[][] ALPHABET_SHIFTED_COMMON = new ExpectedKeyboardBuilder()
+            .setKeysOfRow(1,
+                    // U+09A2: "ঢ" BENGALI LETTER DDHA
+                    key("\u09A2"),
+                    // U+09A0: "ঠ" BENGALI LETTER TTHA
+                    key("\u09A0"),
+                    // U+09C8: "ৈ" BENGALI VOWEL SIGN AI
+                    // U+0990: "ঐ" BENGALI LETTER AI
+                    key("\u09C8", moreKey("\u0990")),
+                    // U+09DC: "ড়" BENGALI LETTER RRA
+                    // U+09BC: "়" BENGALI SIGN NUKTA
+                    key("\u09DC", moreKey("\u09BC")),
+                    // U+099F: "ট" BENGALI LETTER TTA
+                    // U+09F3: "৳" BENGALI RUPEE SIGN
+                    // U+099F/U+09CD/U+099F:
+                    //     "ট্ট" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+099F/U+09CD/U+09AC:
+                    //     "ট্ব" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+099F/U+09CD/U+09AE:
+                    //     "ট্ম" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    key("\u099F", joinMoreKeys("\u09F3", "\u099F\u09CD\u099F", "\u099F\u09CD\u09AC",
+                            "\u099F\u09CD\u09AE")),
+                    // U+099E: "ঞ" BENGALI LETTER NYA
+                    // U+099E/U+09CD/U+099A:
+                    //     "ঞ্চ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                    // U+099E/U+09CD/U+099B:
+                    //     "ঞ্ছ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                    // U+099E/U+09CD/U+099C:
+                    //     "ঞ্জ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                    key("\u099E", joinMoreKeys("\u099E\u09CD\u099A", "\u099E\u09CD\u099B",
+                            "\u099E\u09CD\u099C")),
+                    // U+09C2: "ূ" BENGALI VOWEL SIGN UU
+                    // U+098A: "ঊ" BENGALI LETTER UU
+                    key("\u09C2", moreKey("\u098A")),
+                    // U+09C0: "ী" BENGALI VOWEL SIGN II
+                    // U+0988: "ঈ" BENGALI LETTER II
+                    key("\u09C0", moreKey("\u0988")),
+                    // U+09CC: "ৌ" BENGALI VOWEL SIGN AU
+                    // U+099A: "ঔ" BENGALI LETTER CA
+                    // U+09D7: "ৗ" BENGALI AU LENGTH MARK
+                    key("\u09CC", joinMoreKeys("\u099A", "\u09D7")),
+                    // U+09AB: "ফ" BENGALI LETTER PHA
+                    // U+09AB/U+09CD/U+099F:
+                    //     "ফ্ট" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09AB/U+09CD/U+09AF:
+                    //     "ফ্য" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09AB/U+09CD/U+09B0:
+                    //     "ফ্র" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AB/U+09CD/U+09B2:
+                    //     "ফ্ল" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09AB", joinMoreKeys("\u09AB\u09CD\u099F", "\u09AB\u09CD\u09AF",
+                            "\u09AB\u09CD\u09B0", "\u09AB\u09CD\u09B2")),
+                    // U+098B: "ঋ" BENGALI LETTER VOCALIC R
+                    // U+098C: "ঌ" BENGALI LETTER VOCALIC L
+                    // U+09E1: "ৡ" BENGALI LETTER VOCALIC LL
+                    // U+09F4: "৴" BENGALI CURRENCY NUMERATOR ONE
+                    // U+09F5: "৵" BENGALI CURRENCY NUMERATOR TWO
+                    // U+09F6: "৶" BENGALI CURRENCY NUMERATOR THREE
+                    // U+09E2: " ৢ" BENGALI VOWEL SIGN VOCALIC L
+                    // U+09E3: " ৣ" BENGALI VOWEL SIGN VOCALIC LL
+                    key("\u098B", joinMoreKeys("\u098C", "\u09E1", "\u09F4", "\u09F5", "\u09F6",
+                            "\u09E2", "\u09E3")))
+            .setKeysOfRow(2,
+                    // U+0985: "অ" BENGALI LETTER A
+                    key("\u0985"),
+                    // U+09B6: "শ" BENGALI LETTER SHA
+                    // U+09B6/U+09CD/U+099A:
+                    //     "শ্চ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                    // U+09B6/U+09CD/U+099B:
+                    //     "শ্ছ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                    // U+09B6/U+09CD/U+09A4:
+                    //     "শ্ত" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09B6/U+09CD/U+09A8:
+                    //     "শ্ন" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09B6/U+09CD/U+09AC:
+                    //     "শ্ব" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B6/U+09CD/U+09AE:
+                    //     "শ্ম" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09B6/U+09CD/U+09B0:
+                    //     "শ্র" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09B6/U+09CD/U+09B2:
+                    //     "শ্ল" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09B6", joinMoreKeys("\u09B6\u09CD\u099A", "\u09B6\u09CD\u099B",
+                            "\u09B6\u09CD\u09A4", "\u09B6\u09CD\u09A8", "\u09B6\u09CD\u09AC",
+                            "\u09B6\u09CD\u09AE", "\u09B6\u09CD\u09B0", "\u09B6\u09CD\u09B2")),
+                    // U+09A1: "ড" BENGALI LETTER DDA
+                    // U+09A1/U+09CD/U+09A1:
+                    //     "ড্ড" BENGALI LETTER DDA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    key("\u09A1", moreKey("\u09A1\u09CD\u09A1")),
+                    // U+09DD: "ঢ়" BENGALI LETTER RHA
+                    key("\u09DD"),
+                    // U+0998: "ঘ" BENGALI LETTER GHA
+                    key("\u0998"),
+                    // U+09B9: "হ" BENGALI LETTER HA
+                    // U+09BD: "ঽ" BENGALI SIGN AVAGRAHA
+                    // U+09B9/U+09CD/U+09A3:
+                    //     "হ্ণ" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                    // U+09B9/U+09CD/U+09A8:
+                    //     "হ্ন" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09B9/U+09CD/U+09AC:
+                    //     "হ্ব" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B9/U+09CD/U+09AE:
+                    //     "হ্ম" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09B9/U+09CD/U+09B0:
+                    //     "হ্র" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09B9/U+09CD/U+09B2:
+                    //     "হ্ল" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09B9", joinMoreKeys("\u09BD", "\u09B9\u09CD\u09A3", "\u09B9\u09CD\u09A8",
+                            "\u09B9\u09CD\u09AC", "\u09B9\u09CD\u09AE", "\u09B9\u09CD\u09B0",
+                            "\u09B9\u09CD\u09B2")),
+                    // U+099D: "ঝ" BENGALI LETTER JHA
+                    key("\u099D"),
+                    // U+0996: "খ" BENGALI LETTER KHA
+                    key("\u0996"),
+                    // U+09CE: "ৎ" BENGALI LETTER KHANDA TA
+                    key("\u09CE"),
+                    // U+0988: "ঈ" BENGALI LETTER II
+                    key("\u0988"),
+                    // U+098A: "ঊ" BENGALI LETTER UU
+                    key("\u098A"))
+            .setKeysOfRow(3,
+                    // U+0964: "।" DEVANAGARI DANDA
+                    // U+0965: "॥" DEVANAGARI DOUBLE DANDA
+                    key("\u0964", moreKey("\u0965")),
+                    // U+0999: "ঙ BENGALI LETTER NGA
+                    // U+0999/U+09CD/U+0995: "ঙ্ক"
+                    // U+0999/U+09CD/U+0996: "ঙ্খ"
+                    // U+0999/U+09CD/U+0997: "ঙ্গ"
+                    key("\u0999", joinMoreKeys("\u0999\u09CD\u0995", "\u0999\u09CD\u0996",
+                            "\u0999\u09CD\u0997")),
+                    // U+099B: "ছ" BENGALI LETTER CHA
+                    key("\u099B"),
+                    // U+0983: "ঃ" BENGALI SIGN VISARGA
+                    key("\u0983"),
+                    // U+0981: "ঁ" BENGALI SIGN CANDRABINDU
+                    key("\u0981"),
+                    // U+09A3: "ণ" BENGALI LETTER NNA
+                    // U+09A3/U+09CD/U+099F:
+                    //     "ণ্ট" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER TT/A
+                    // U+09A3/U+09CD/U+09A1:
+                    //     "ণ্ড" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    // U+09A3/U+09CD/U+09A3:
+                    //     "ণ্ণ" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER NN
+                    key("\u09A3", joinMoreKeys("\u09A3\u09CD\u099F", "\u09A3\u09CD\u09A1",
+                            "\u09A3\u09CD\u09A3")),
+                    // U+0982: "ং" BENGALI SIGN ANUSVARA
+                    key("\u0982"),
+                    // U+0990: "ঐ" BENGALI LETTER AI
+                    key("\u0990"),
+                    // U+0994: "ঔ" BENGALI LETTER AU
+                    key("\u0994"))
+            .build();
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java b/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java
index b12b8be..a080cac 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java
@@ -21,9 +21,6 @@
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
 
 /**
  * The Hindi keyboard.
@@ -38,50 +35,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class HindiCustomizer extends LayoutCustomizer {
-        public HindiCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey getAlphabetKey() { return HINDI_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey getSymbolsKey() { return HINDI_SYMBOLS_KEY; }
-
-        @Override
-        public ExpectedKey getBackToSymbolsKey() { return HINDI_BACK_TO_SYMBOLS_KEY; }
-
-        @Override
-        public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
-
-        @Override
-        public ExpectedKey[] getOtherCurrencyKeys() {
-            return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
-        }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        // U+0915: "क" DEVANAGARI LETTER KA
-        // U+0916: "ख" DEVANAGARI LETTER KHA
-        // U+0917: "ग" DEVANAGARI LETTER GA
-        private static final ExpectedKey HINDI_ALPHABET_KEY = key(
-                "\u0915\u0916\u0917", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-        // U+0967: "१" DEVANAGARI DIGIT ONE
-        // U+0968: "२" DEVANAGARI DIGIT TWO
-        // U+0969: "३" DEVANAGARI DIGIT THREE
-        private static final String HINDI_SYMBOLS_LABEL = "?\u0967\u0968\u0969";
-        private static final ExpectedKey HINDI_SYMBOLS_KEY = key(HINDI_SYMBOLS_LABEL,
-                Constants.CODE_SWITCH_ALPHA_SYMBOL);
-        private static final ExpectedKey HINDI_BACK_TO_SYMBOLS_KEY = key(HINDI_SYMBOLS_LABEL,
-                Constants.CODE_SHIFT);
-
-        // U+20B9: "₹" INDIAN RUPEE SIGN
-        private static final ExpectedKey CURRENCY_RUPEE = key("\u20B9",
-                Symbols.CURRENCY_GENERIC_MORE_KEYS);
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java b/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java
index c2a15f3..457851b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java
@@ -18,10 +18,10 @@
 
 import static com.android.inputmethod.keyboard.layout.DevanagariLetterConstants.*;
 
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.Hindi.HindiSymbols;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.tests.HindiCustomizer;
 
 import java.util.Locale;
 
@@ -45,27 +45,6 @@
         public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
             return EMPTY_KEYS;
         }
-
-        @Override
-        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            // U+0964: "।" DEVANAGARI DANDA
-            final ExpectedKey periodKey = key("\u0964", getPunctuationMoreKeys(isPhone));
-            return joinKeys(periodKey);
-        }
-
-        @Override
-        public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
-            return isPhone ? HINDI_PHONE_PUNCTUATION_MORE_KEYS : HINDI_TABLET_PUNCTUATION_MORE_KEYS;
-        }
-
-        // Punctuation more keys for phone form factor.
-        private static final ExpectedKey[] HINDI_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
-                ",", ".", "?", "!", "#", ")", "(", "/", ";",
-                "'", "@", ":", "-", "\"", "+", "%", "&");
-        // Punctuation more keys for tablet form factor.
-        private static final ExpectedKey[] HINDI_TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
-                ",", ".", "'", "#", ")", "(", "/", ";",
-                "@", ":", "-", "\"", "+", "%", "&");
     }
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java b/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java
index 00cf838..615ec89 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java
@@ -18,10 +18,10 @@
 
 import static com.android.inputmethod.keyboard.layout.DevanagariLetterConstants.*;
 
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.Hindi.HindiSymbols;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.tests.DevanagariCustomizer;
 
 import java.util.Locale;
 
@@ -38,7 +38,7 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class MarathiCustomizer extends HindiCustomizer {
+    public static class MarathiCustomizer extends DevanagariCustomizer {
         public MarathiCustomizer(final Locale locale) { super(locale); }
 
         @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java b/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java
index 7933d07..fec2261 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java
@@ -19,10 +19,10 @@
 import static com.android.inputmethod.keyboard.layout.DevanagariLetterConstants.*;
 
 import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.Hindi.HindiSymbols;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.tests.DevanagariCustomizer;
 
 import java.util.Locale;
 
@@ -39,7 +39,7 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class NepaliRomanizedCustomizer extends HindiCustomizer {
+    public static class NepaliRomanizedCustomizer extends DevanagariCustomizer {
         public NepaliRomanizedCustomizer(final Locale locale) { super(locale); }
 
         @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Uzbek.java b/tests/src/com/android/inputmethod/keyboard/layout/Uzbek.java
new file mode 100644
index 0000000..df391a5
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Uzbek.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+/**
+ * The Uzbek alphabet keyboard.
+ */
+public final class Uzbek extends LayoutBase {
+    private static final String LAYOUT_NAME = "uzbek";
+
+    public Uzbek(final LayoutCustomizer customizer) {
+        super(customizer, Symbols.class, SymbolsShifted.class);
+    }
+
+    @Override
+    public String getName() { return LAYOUT_NAME; }
+
+    @Override
+    ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
+
+    public static final String ROW1_11 = "ROW1_11";
+    public static final String ROW2_10 = "ROW2_10";
+    public static final String ROW2_11 = "ROW2_11";
+
+    private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
+            .setKeysOfRow(1,
+                    key("q", additionalMoreKey("1")),
+                    key("w", additionalMoreKey("2")),
+                    key("e", additionalMoreKey("3")),
+                    key("r", additionalMoreKey("4")),
+                    key("t", additionalMoreKey("5")),
+                    key("y", additionalMoreKey("6")),
+                    key("u", additionalMoreKey("7")),
+                    key("i", additionalMoreKey("8")),
+                    key("o", additionalMoreKey("9")),
+                    key("p", additionalMoreKey("0")),
+                    ROW1_11)
+            .setKeysOfRow(2, "a", "s", "d", "f", "g", "h", "j", "k", "l", ROW2_10, ROW2_11)
+            .setKeysOfRow(3, "z", "x", "c", "v", "b", "n", "m")
+            .build();
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/BengaliCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/BengaliCustomizer.java
new file mode 100644
index 0000000..7964b64
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/BengaliCustomizer.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout.tests;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.latin.Constants;
+
+import java.util.Locale;
+
+public class BengaliCustomizer extends LayoutCustomizer {
+    public BengaliCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey getAlphabetKey() { return BENGALI_ALPHABET_KEY; }
+
+    @Override
+    public ExpectedKey[] getOtherCurrencyKeys() {
+        return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+    }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : LayoutBase.EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    // U+0995: "क" BENGALI LETTER KA
+    // U+0996: "ख" BENGALI LETTER KHA
+    // U+0997: "ग" BENGALI LETTER GA
+    private static final ExpectedKey BENGALI_ALPHABET_KEY = LayoutBase.key(
+            "\u0995\u0996\u0997", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/DevanagariCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/DevanagariCustomizer.java
new file mode 100644
index 0000000..a31591d
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/DevanagariCustomizer.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout.tests;
+
+import com.android.inputmethod.keyboard.layout.Hindi;
+import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.latin.Constants;
+
+import java.util.Locale;
+
+public class DevanagariCustomizer extends LayoutCustomizer {
+    public DevanagariCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey getAlphabetKey() { return HINDI_ALPHABET_KEY; }
+
+    @Override
+    public ExpectedKey getSymbolsKey() { return HINDI_SYMBOLS_KEY; }
+
+    @Override
+    public ExpectedKey getBackToSymbolsKey() { return HINDI_BACK_TO_SYMBOLS_KEY; }
+
+    @Override
+    public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
+
+    @Override
+    public ExpectedKey[] getOtherCurrencyKeys() {
+        return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+    }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : Hindi.EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    // U+0915: "क" DEVANAGARI LETTER KA
+    // U+0916: "ख" DEVANAGARI LETTER KHA
+    // U+0917: "ग" DEVANAGARI LETTER GA
+    private static final ExpectedKey HINDI_ALPHABET_KEY = Hindi.key(
+            "\u0915\u0916\u0917", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    // U+0967: "१" DEVANAGARI DIGIT ONE
+    // U+0968: "२" DEVANAGARI DIGIT TWO
+    // U+0969: "३" DEVANAGARI DIGIT THREE
+    private static final String HINDI_SYMBOLS_LABEL = "?\u0967\u0968\u0969";
+    private static final ExpectedKey HINDI_SYMBOLS_KEY = Hindi.key(HINDI_SYMBOLS_LABEL,
+            Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    private static final ExpectedKey HINDI_BACK_TO_SYMBOLS_KEY = Hindi.key(HINDI_SYMBOLS_LABEL,
+            Constants.CODE_SHIFT);
+
+    // U+20B9: "₹" INDIAN RUPEE SIGN
+    private static final ExpectedKey CURRENCY_RUPEE = Hindi.key("\u20B9",
+            Symbols.CURRENCY_GENERIC_MORE_KEYS);
+}
\ No newline at end of file
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/HindiCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/HindiCustomizer.java
new file mode 100644
index 0000000..cb53bdc
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/HindiCustomizer.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout.tests;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+public class HindiCustomizer extends DevanagariCustomizer {
+    public HindiCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
+        // U+0964: "।" DEVANAGARI DANDA
+        final ExpectedKey periodKey = LayoutBase.key("\u0964", getPunctuationMoreKeys(isPhone));
+        return LayoutBase.joinKeys(periodKey);
+    }
+
+    @Override
+    public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
+        return isPhone ? HINDI_PHONE_PUNCTUATION_MORE_KEYS : HINDI_TABLET_PUNCTUATION_MORE_KEYS;
+    }
+
+    // Punctuation more keys for phone form factor.
+    private static final ExpectedKey[] HINDI_PHONE_PUNCTUATION_MORE_KEYS = LayoutBase.joinKeys(
+            ",", ".", "?", "!", "#", ")", "(", "/", ";",
+            "'", "@", ":", "-", "\"", "+", "%", "&");
+    // Punctuation more keys for tablet form factor.
+    private static final ExpectedKey[] HINDI_TABLET_PUNCTUATION_MORE_KEYS = LayoutBase.joinKeys(
+            ",", ".", "'", "#", ")", "(", "/", ";",
+            "@", ":", "-", "\"", "+", "%", "&");
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java
new file mode 100644
index 0000000..0334d5d
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.BengaliAkkhor;
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+/**
+ * bn_BD: Bengali (Bangladesh)/bengali_akkhor
+ */
+@SmallTest
+public final class TestsBengaliBD extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("bn", "BD");
+    private static final LayoutBase LAYOUT = new BengaliAkkhor(new BengaliBDCustomzier(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class BengaliBDCustomzier extends BengaliCustomizer {
+        public BengaliBDCustomzier(final Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+            return isPhone ? EMPTY_KEYS : LayoutBase.EXCLAMATION_AND_QUESTION_MARKS;
+        }
+
+        @Override
+        public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
+
+        // U+09F3: "৳" BENGALI RUPEE SIGN
+        private static final ExpectedKey CURRENCY_RUPEE = key("\u09F3",
+                Symbols.CURRENCY_GENERIC_MORE_KEYS);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java
index d642632..91a976c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Bengali;
-import com.android.inputmethod.keyboard.layout.Bengali.BengaliCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Symbols;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
@@ -41,6 +40,9 @@
         public BengaliINCustomzier(final Locale locale) { super(locale); }
 
         @Override
+        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) { return EMPTY_KEYS; }
+
+        @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
 
         // U+20B9: "₹" INDIAN RUPEE SIGN
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java
index 84053b5..abea51a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Hindi;
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java
new file mode 100644
index 0000000..e8801dd
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Uzbek;
+
+import java.util.Locale;
+
+/**
+ * uz_UZ: Uzbek (Uzbekistan)/uzbek
+ */
+@SmallTest
+public final class TestsUzbek extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("uz", "UZ");
+    private static final LayoutBase LAYOUT = new Uzbek(new UzbekCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java
new file mode 100644
index 0000000..dec587f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * uz_UZ: Uzbek (Uzbekistan)/qwerty
+ */
+@SmallTest
+public final class TestsUzbekQwerty extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("uz", "UZ");
+    private static final LayoutBase LAYOUT = new Qwerty(new UzbekQwertyCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class UzbekQwertyCustomizer extends UzbekCustomizer {
+        public UzbekQwertyCustomizer(final Locale locale) {
+            super(locale);
+        }
+
+        @Override
+        protected void setUzbekKeys(final ExpectedKeyboardBuilder builder) {
+            // QWERTY layout doesn't have Uzebk keys.
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/UzbekCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/UzbekCustomizer.java
new file mode 100644
index 0000000..6da0b0e
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/UzbekCustomizer.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.layout.tests;
+
+import com.android.inputmethod.keyboard.layout.Nordic;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+class UzbekCustomizer extends TurkicCustomizer {
+    public UzbekCustomizer(final Locale locale) {
+        super(locale);
+    }
+
+    protected void setUzbekKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+006F/U+02BB: "oʻ" LATIN SMALL LETTER O/MODIFIER LETTER TURNED COMMA
+                .replaceKeyOfLabel(Nordic.ROW1_11, "o\u02BB")
+                // U+0067/U+02BB: "gʻ" LATIN SMALL LETTER G/MODIFIER LETTER TURNED COMMA
+                .replaceKeyOfLabel(Nordic.ROW2_10, "g\u02BB")
+                // U+02BC: "ʼ" MODIFIER LETTER APOSTROPHE
+                .replaceKeyOfLabel(Nordic.ROW2_11, "\u02BC");
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        setUzbekKeys(builder);
+        return super.setAccentedLetters(builder);
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index e6f00b6..9c7792c 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -1105,7 +1105,7 @@
             assertTrue(wordProperty.isValid());
             assertEquals(isNotAWord, wordProperty.mIsNotAWord);
             assertEquals(isBlacklisted, wordProperty.mIsBlacklistEntry);
-            assertEquals(false, wordProperty.mHasBigrams);
+            assertEquals(false, wordProperty.mHasNgrams);
             assertEquals(false, wordProperty.mHasShortcuts);
             assertEquals(unigramProbability, wordProperty.mProbabilityInfo.mProbability);
             assertTrue(wordProperty.mShortcutTargets.isEmpty());
@@ -1142,13 +1142,14 @@
             final HashSet<String> bigramWord1s = bigrams.get(word0);
             final WordProperty wordProperty = binaryDictionary.getWordProperty(word0,
                     false /* isBeginningOfSentence */);
-            assertEquals(bigramWord1s.size(), wordProperty.mBigrams.size());
-            for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
-                final String word1 = wordProperty.mBigrams.get(j).mWord;
+            assertEquals(bigramWord1s.size(), wordProperty.mNgrams.size());
+            // TODO: Support ngram.
+            for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+                final String word1 = bigramTarget.mWord;
                 assertTrue(bigramWord1s.contains(word1));
                 if (canCheckBigramProbability(formatVersion)) {
                     final int bigramProbability = bigramProbabilities.get(new Pair<>(word0, word1));
-                    assertEquals(bigramProbability, wordProperty.mBigrams.get(j).getProbability());
+                    assertEquals(bigramProbability, bigramTarget.getProbability());
                 }
             }
         }
@@ -1235,13 +1236,14 @@
                     wordProperty.mProbabilityInfo.mProbability);
             wordSet.remove(word0);
             final HashSet<String> bigramWord1s = bigrams.get(word0);
-            for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
-                final String word1 = wordProperty.mBigrams.get(j).mWord;
+            // TODO: Support ngram.
+            for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+                final String word1 = bigramTarget.mWord;
                 assertTrue(bigramWord1s.contains(word1));
                 final Pair<String, String> bigram = new Pair<>(word0, word1);
                 if (canCheckBigramProbability(formatVersion)) {
                     final int bigramProbability = bigramProbabilitiesToCheckLater.get(bigram);
-                    assertEquals(bigramProbability, wordProperty.mBigrams.get(j).getProbability());
+                    assertEquals(bigramProbability, bigramTarget.getProbability());
                 }
                 bigramSet.remove(bigram);
             }
diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
index 6e894de..30b0881 100644
--- a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
+++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
@@ -63,7 +63,7 @@
         final int typedLength = STRING_TO_TYPE.length();
         final int EXPECTED_SUGGESTION_SPAN_START = -1;
         final int EXPECTED_UNDERLINE_SPAN_START = 0;
-        final int EXPECTED_UNDERLINE_SPAN_END = 4;
+        final int EXPECTED_UNDERLINE_SPAN_END = 3;
         type(STRING_TO_TYPE);
         sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
         runMessages();
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 59b858d..ec249da 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -159,8 +159,11 @@
     }
 
     public void testAutoCorrectWithSpaceThenRevert() {
+        // Backspacing to cancel the "tgis"->"this" autocorrection should result in
+        // a "phantom space": if the user presses space immediately after,
+        // only one space will be inserted in total.
         final String STRING_TO_TYPE = "tgis ";
-        final String EXPECTED_RESULT = "tgis ";
+        final String EXPECTED_RESULT = "tgis";
         type(STRING_TO_TYPE);
         mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
         type(Constants.CODE_DELETE);
@@ -168,6 +171,24 @@
                 mEditText.getText().toString());
     }
 
+    public void testAutoCorrectWithSpaceThenRevertThenTypeMore() {
+        final String STRING_TO_TYPE_FIRST = "tgis ";
+        final String STRING_TO_TYPE_SECOND = "a";
+        final String EXPECTED_RESULT = "tgis a";
+        type(STRING_TO_TYPE_FIRST);
+        mLatinIME.onUpdateSelection(0, 0,
+                STRING_TO_TYPE_FIRST.length(), STRING_TO_TYPE_FIRST.length(), -1, -1);
+        type(Constants.CODE_DELETE);
+
+        type(STRING_TO_TYPE_SECOND);
+        mLatinIME.onUpdateSelection(STRING_TO_TYPE_FIRST.length(), STRING_TO_TYPE_FIRST.length(),
+                STRING_TO_TYPE_FIRST.length() - 1 + STRING_TO_TYPE_SECOND.length(),
+                STRING_TO_TYPE_FIRST.length() - 1 + STRING_TO_TYPE_SECOND.length(),
+                -1, -1);
+        assertEquals("auto-correct with space then revert then type more", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
     public void testAutoCorrectToSelfDoesNotRevert() {
         final String STRING_TO_TYPE = "this ";
         final String EXPECTED_RESULT = "this";
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index 406046a..f8b68e0 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -682,8 +682,8 @@
                 }
                 assertTrue(shortcutList.isEmpty());
             }
-            for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
-                final String word1 = wordProperty.mBigrams.get(j).mWord;
+            for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+                final String word1 = bigramTarget.mWord;
                 final Pair<String, String> bigram = new Pair<>(word0, word1);
                 assertTrue(bigramSet.contains(bigram));
                 bigramSet.remove(bigram);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
index 65b84d5..18f4bcf 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
@@ -292,11 +292,11 @@
         }
         // Insert bigrams into the fusion dictionary.
         for (final WordProperty wordProperty : wordProperties) {
-            if (wordProperty.mBigrams == null) {
+            if (!wordProperty.mHasNgrams) {
                 continue;
             }
             final String word0 = wordProperty.mWord;
-            for (final WeightedString bigram : wordProperty.mBigrams) {
+            for (final WeightedString bigram : wordProperty.getBigrams()) {
                 fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo);
             }
         }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 5e8417e..0da915a 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -97,12 +97,13 @@
             }
         }
         // Insert bigrams into the fusion dictionary.
+        // TODO: Support ngrams.
         for (final WordProperty wordProperty : wordProperties) {
-            if (wordProperty.mBigrams == null) {
+            if (!wordProperty.mHasNgrams) {
                 continue;
             }
             final String word0 = wordProperty.mWord;
-            for (final WeightedString bigram : wordProperty.mBigrams) {
+            for (final WeightedString bigram : wordProperty.getBigrams()) {
                 fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo);
             }
         }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
index 74da937..401ffde 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
@@ -102,8 +102,9 @@
             }
         }
         for (final WordProperty word0Property : dict) {
-            if (null == word0Property.mBigrams) continue;
-            for (final WeightedString word1 : word0Property.mBigrams) {
+            if (!word0Property.mHasNgrams) continue;
+            // TODO: Support ngram.
+            for (final WeightedString word1 : word0Property.getBigrams()) {
                 final NgramContext ngramContext =
                         new NgramContext(new NgramContext.WordInfo(word0Property.mWord));
                 if (!binaryDict.addNgramEntry(ngramContext, word1.mWord,
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java
index 94d1ae8..c6818ce 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java
@@ -135,7 +135,7 @@
                     hasDifferences = true;
                 }
                 hasDifferences |= hasAttributesDifferencesAndPrintThemIfAny(word0Property.mWord,
-                        "Bigram", word0Property.mBigrams, word1PtNode.getBigrams());
+                        "Bigram", word0Property.getBigrams(), word1PtNode.getBigrams());
                 hasDifferences |= hasAttributesDifferencesAndPrintThemIfAny(word0Property.mWord,
                         "Shortcut", word0Property.mShortcutTargets,
                         word1PtNode.getShortcutTargets());
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
index 9b2567f..2850e1f 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
@@ -45,8 +45,8 @@
         int whitelistCount = 0;
         for (final WordProperty wordProperty : dict) {
             ++wordCount;
-            if (null != wordProperty.mBigrams) {
-                bigramCount += wordProperty.mBigrams.size();
+            if (wordProperty.mHasNgrams) {
+                bigramCount += wordProperty.mNgrams.size();
             }
             if (null != wordProperty.mShortcutTargets) {
                 shortcutCount += wordProperty.mShortcutTargets.size();
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
index bdec447..cd3ce70 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
@@ -353,7 +353,7 @@
                     + "\" " + PROBABILITY_ATTR + "=\"" + wordProperty.getProbability()
                     + (wordProperty.mIsNotAWord ? "\" " + NOT_A_WORD_ATTR + "=\"true" : "")
                     + "\">");
-            if (null != wordProperty.mShortcutTargets) {
+            if (wordProperty.mHasShortcuts) {
                 destination.write("\n");
                 for (WeightedString target : wordProperty.mShortcutTargets) {
                     destination.write("    <" + SHORTCUT_TAG + " " + PROBABILITY_ATTR + "=\""
@@ -362,9 +362,9 @@
                 }
                 destination.write("  ");
             }
-            if (null != wordProperty.mBigrams) {
+            if (wordProperty.mHasNgrams) {
                 destination.write("\n");
-                for (WeightedString bigram : wordProperty.mBigrams) {
+                for (WeightedString bigram : wordProperty.getBigrams()) {
                     destination.write("    <" + BIGRAM_TAG + " " + PROBABILITY_ATTR + "=\""
                             + bigram.getProbability() + "\">" + bigram.mWord
                             + "</" + BIGRAM_TAG + ">\n");
diff --git a/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml
index a68de67..52fe565 100644
--- a/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml
@@ -18,6 +18,7 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- This is the same as Turkish -->
     <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
          U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
          U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE -->
diff --git a/tools/make-keyboard-text/res/values-bn-rBD/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-bn-rBD/donottranslate-more-keys.xml
new file mode 100644
index 0000000..4955cd4
--- /dev/null
+++ b/tools/make-keyboard-text/res/values-bn-rBD/donottranslate-more-keys.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Label for "switch to alphabetic" key.
+         U+0995: "क" BENGALI LETTER KA
+         U+0996: "ख" BENGALI LETTER KHA
+         U+0997: "ग" BENGALI LETTER GA -->
+    <string name="keylabel_to_alpha">&#x0995;&#x0996;&#x0997;</string>
+    <!-- U+09F3: "৳" BENGALI RUPEE SIGN -->
+    <string name="keyspec_currency">&#x09F3;</string>
+</resources>
diff --git a/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml
index 55723cd..2a37d8b 100644
--- a/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml
@@ -57,4 +57,9 @@
     <string name="additional_morekeys_symbols_0">0</string>
     <!-- U+20B9: "₹" INDIAN RUPEE SIGN -->
     <string name="keyspec_currency">&#x20B9;</string>
+    <!-- U+0964: "।" DEVANAGARI DANDA -->
+    <string name="keyspec_period">&#x0964;</string>
+    <string name="keyspec_tablet_period">&#x0964;</string>
+    <string name="morekeys_period">"!autoColumnOrder!9,\\,,.,?,!,#,),(,/,;,',@,:,-,\",+,\\%,&amp;"</string>
+    <string name="morekeys_tablet_period">"!autoColumnOrder!8,\\,,.,',#,),(,/,;,@,:,-,\",+,\\%,&amp;"</string>
 </resources>
diff --git a/tools/make-keyboard-text/res/values-uz-rUZ/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-uz-rUZ/donottranslate-more-keys.xml
new file mode 100644
index 0000000..24dd091
--- /dev/null
+++ b/tools/make-keyboard-text/res/values-uz-rUZ/donottranslate-more-keys.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- This is the same as Turkish -->
+    <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+         U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE -->
+    <string name="morekeys_a">&#x00E2;,&#x00E4;,&#x00E1;</string>
+    <!-- U+0259: "ə" LATIN SMALL LETTER SCHWA
+         U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE -->
+    <string name="morekeys_e">&#x0259;,&#x00E9;</string>
+    <!-- U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+         U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+         U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+         U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+         U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+         U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+         U+012B: "ī" LATIN SMALL LETTER I WITH MACRON -->
+    <string name="morekeys_i">&#x0131;,&#x00EE;,&#x00EF;,&#x00EC;,&#x00ED;,&#x012F;,&#x012B;</string>
+    <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+         U+0153: "œ" LATIN SMALL LIGATURE OE
+         U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+         U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+         U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+         U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+         U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
+    <string name="morekeys_o">&#x00F6;,&#x00F4;,&#x0153;,&#x00F2;,&#x00F3;,&#x00F5;,&#x00F8;,&#x014D;</string>
+    <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+         U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+         U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+         U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+         U+016B: "ū" LATIN SMALL LETTER U WITH MACRON -->
+    <string name="morekeys_u">&#x00FC;,&#x00FB;,&#x00F9;,&#x00FA;,&#x016B;</string>
+    <!-- U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+         U+00DF: "ß" LATIN SMALL LETTER SHARP S
+         U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+         U+0161: "š" LATIN SMALL LETTER S WITH CARON -->
+    <string name="morekeys_s">&#x015F;,&#x00DF;,&#x015B;,&#x0161;</string>
+    <!-- U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE -->
+    <string name="morekeys_g">&#x011F;</string>
+    <!-- U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+         U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->
+    <string name="morekeys_n">&#x0148;,&#x00F1;</string>
+    <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+         U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+         U+010D: "č" LATIN SMALL LETTER C WITH CARON -->
+    <string name="morekeys_c">&#x00E7;,&#x0107;,&#x010D;</string>
+    <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE -->
+    <string name="morekeys_y">&#x00FD;</string>
+    <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON -->
+    <string name="morekeys_z">&#x017E;</string>
+</resources>