Merge "Import translations. DO NOT MERGE"
diff --git a/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png
index 2cfe1d4..b1fe2c0 100644
--- a/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png
index ff49d58..e639416 100644
--- a/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png
index df3eba7..0d8c33b 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png
index 08d4f8a..ef5bf5a 100644
--- a/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 7e9546b..c1b7b76 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Geen steminvoermetodes geaktiveer nie. Gaan taal- en invoerinstellings na."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Stel invoermetodes op"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Invoertale"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Stuur terugvoer"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Hulp en terugvoering"</string>
     <string name="select_language" msgid="3693815588777926848">"Invoertale"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak weer om te stoor"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordeboek beskikbaar"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 6d43829..15440fc 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ምንም የግቤት ስልቶች አልነቁም። የቋንቋ እና የግቤት ቅንብሮችን ይፈትሹ።"</string>
     <string name="configure_input_method" msgid="373356270290742459">"ግቤት ሜተዶችን አዋቀር"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ቋንቋዎች አግቤት"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ግብረ-መልስ ላክ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"እገዛ እና ግብረመልስ"</string>
     <string name="select_language" msgid="3693815588777926848">"ቋንቋዎች አግቤት"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ለማስቀመጥ እንደገና ንካ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"መዝገበ ቃላት አለ"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 0365947..b6252c8 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"لم يتم تمكين أي أساليب إدخال صوتي. تحقق من إعدادات اللغة والإدخال."</string>
     <string name="configure_input_method" msgid="373356270290742459">"تهيئة طرق الإدخال"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"لغات الإدخال"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"إرسال تعليقات"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"المساعدة والتعليقات"</string>
     <string name="select_language" msgid="3693815588777926848">"لغات الإدخال"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"المس مرة أخرى للحفظ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"القاموس متاح"</string>
diff --git a/java/res/values-az-rAZ/strings.xml b/java/res/values-az-rAZ/strings.xml
index f745a3e..1d11e84 100644
--- a/java/res/values-az-rAZ/strings.xml
+++ b/java/res/values-az-rAZ/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Heç bir səs daxiletmə metodu aktiv deyil. Dil və daxiletmə ayarlarını yoxlayın."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Daxiletmə üsullarını sazla"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Daxiletmə dilləri"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Cavab rəyi göndərin"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Yardım və geri əlaqə"</string>
     <string name="select_language" msgid="3693815588777926848">"Daxiletmə dilləri"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Yadda saxlamaq üçün yenidən toxunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Lüğət mövcuddur"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 8768f00..515051a 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Няма активирани методи на гласово въвеждане. Проверете настройките за език и въвеждане."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Конфигуриране на въвеждането"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Входни езици"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Изпращане на отзиви"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Езици за въвеждане"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Докоснете отново, за да запазите"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Има достъп до речник"</string>
diff --git a/java/res/values-bn-rBD/strings.xml b/java/res/values-bn-rBD/strings.xml
index 615e561..48c887d 100644
--- a/java/res/values-bn-rBD/strings.xml
+++ b/java/res/values-bn-rBD/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"কোনো ভয়েস ইনপুট পদ্ধতি সক্ষম নয়। ভাষা &amp; ইনপুট সেটিংস পরীক্ষা করুন।"</string>
     <string name="configure_input_method" msgid="373356270290742459">"ইনপুট পদ্ধতি কনফিগার করুন"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ইনপুট ভাষাগুলি"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"প্রতিক্রিয়া পাঠান"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"ইনপুট ভাষাগুলি"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"সংরক্ষণ করতে আবার ছোঁন"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"অভিধান উপলব্ধ"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 0f27cc6..933112c 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No hi ha cap mètode d\'introducció activat. Comprova la configuració d\'Idioma i introducció de text."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configura mètodes d\'entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomes"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Envia comentaris"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Idiomes d\'introducció"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Torna a tocar per desar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionari disponible"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 2cfffca..4c884cf 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nejsou povoleny žádné metody hlasového vstupu. Zkontrolujte nastavení Jazyk a vstup."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurace metod zadávání"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Vstupní jazyky"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Odeslat zpětnou vazbu"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Vstupní jazyky"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opětovným dotykem provedete uložení"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovník k dispozici"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 6c94f3a..4b821b4 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Der er ingen aktiverede stemmeinputmetoder. Kontrollér Indstillinger for sprog og input."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inputmetoder"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Inputsprog"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Inputsprog"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index fb9e84a..1fe242a 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Keine Spracheingabemethoden aktiviert. Rufen Sie die Einstellungen für \"Sprache &amp; Eingabe\" auf."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Eingabemethoden konfigurieren"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Eingabesprachen"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Feedback geben"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Eingabesprachen"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Zum Speichern erneut berühren"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfügbar"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 1edc5b3..0c1bca3 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Δεν έχουν ενεργοποιηθεί μέθοδοι φωνητικής εισαγωγής. Ελέγξτε τις Ρυθμίσεις Γλώσσας και εισαγωγής."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Διαμόρφωση μεθόδων εισαγωγής"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Γλώσσες εισόδου"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Αποστολή σχολίων"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Γλώσσες εισόδου"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Αγγίξτε ξανά για αποθήκευση"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Λεξικό διαθέσιμο"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 810be5c..a8a7ade 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No voice input methods enabled. Check Language &amp; input settings."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Help &amp; feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Input languages"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
diff --git a/java/res/values-en-rIN/strings.xml b/java/res/values-en-rIN/strings.xml
index 810be5c..a8a7ade 100644
--- a/java/res/values-en-rIN/strings.xml
+++ b/java/res/values-en-rIN/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No voice input methods enabled. Check Language &amp; input settings."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Help &amp; feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Input languages"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index aeb9bc3..e810c0b 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No hay métodos de entrada de voz habilitados. Comprueba la configuración de Teclado e idioma."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentarios"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Vuelve a tocar para guardar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 852dbd4..ef227bd 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Sin métodos de introducción de voz habilitados. Comprueba ajustes de Idioma e introducción de texto."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Danos tu opinión"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Idiomas de introducción"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca otra vez para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string>
diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml
index e62dd64..243d913 100644
--- a/java/res/values-et-rEE/strings.xml
+++ b/java/res/values-et-rEE/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ühtegi häälsisendmeetodit pole lubatud. Kontrollige keele- ja sisendiseadeid."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Sisestusmeetodite seadistamine"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Sisestuskeeled"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Saatke tagasisidet"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Sisestuskeeled"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Salvestamiseks puudutage uuesti"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sõnastik saadaval"</string>
diff --git a/java/res/values-eu-rES/strings.xml b/java/res/values-eu-rES/strings.xml
index 105b51d..5b86ae3 100644
--- a/java/res/values-eu-rES/strings.xml
+++ b/java/res/values-eu-rES/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ez da ahots bidezko idazketa-metodorik gaitu. Egiaztatu Hizkuntza eta idazketa ataleko ezarpenak."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguratu idazketa-metodoak"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idazketa-hizkuntzak"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Bidali oharrak"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Idazketa-hizkuntzak"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gordetzeko, ukitu berriro"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hiztegia erabilgarri"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index ee39cbc..ff68313 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"هیچ روش ورودی صوتی فعال نشده است. تنظیمات زبان و ورودی را بررسی کنید."</string>
     <string name="configure_input_method" msgid="373356270290742459">"پیکربندی روش‌های ورودی"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"زبان‌های ورودی"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ارسال بازخورد"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"راهنما و بازخورد"</string>
     <string name="select_language" msgid="3693815588777926848">"زبان‌های ورودی"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"برای ذخیره دوباره لمس کنید"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"دیکشنری موجود است"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 32d2590..1f06b07 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Äänen syöttötapoja ei ole otettu käyttöön. Tarkista Kieli ja syöttötapa -asetukset."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Määritä syöttötavat"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Syöttökielet"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Lähetä palautetta"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ohje ja palaute"</string>
     <string name="select_language" msgid="3693815588777926848">"Syöttökielet"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tallenna koskettamalla uudelleen"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sanakirja saatavilla"</string>
diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml
index 3a961b0..4c6d82c 100644
--- a/java/res/values-fr-rCA/strings.xml
+++ b/java/res/values-fr-rCA/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Aucun mode d\'entrée vocale n\'a été activé. Vérifiez les paramètres de langues et d\'entrée de texte."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 667710d..077ead3 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Aucun mode de saisie vocale activé. Vérifiez les paramètres de langue et de saisie."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
diff --git a/java/res/values-gl-rES/strings.xml b/java/res/values-gl-rES/strings.xml
index 899942e..8d5bd0b 100644
--- a/java/res/values-gl-rES/strings.xml
+++ b/java/res/values-gl-rES/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Non hai ningún método de entrada de voz activado. Comproba a configuración de Idioma e entrada de texto."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentarios"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca de novo para gardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionario dispoñible"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index c6b0099..754ddc5 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -51,7 +51,7 @@
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"स्पेसबार पर डबल टैप करने से पीरियड शामिल हो जाता है जिसके बाद एक रिक्ति होती है"</string>
     <string name="auto_cap" msgid="1719746674854628252">"स्‍वत: अक्षर बड़े करना"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"प्रत्येक वाक्य के पहले शब्द को बड़ा लिखें"</string>
-    <string name="edit_personal_dictionary" msgid="3996910038952940420">"व्यक्तिगत शब्दकोश"</string>
+    <string name="edit_personal_dictionary" msgid="3996910038952940420">"निजी शब्दकोश"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"एड-ऑन शब्दकोश"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"मुख्‍य डिक्‍शनरी"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"सुधार सुझाव दिखाएं"</string>
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"कोई ध्वनि इनपुट पद्धति सक्षम नहीं है. भाषा और इनपुट सेटिंग जांचें."</string>
     <string name="configure_input_method" msgid="373356270290742459">"इनपुट पद्धति कॉन्‍फ़िगर करें"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"इनपुट भाषा"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"सुझाव भेजें"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"इनपुट भाषाएं"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"सहेजने के लिए पुन: स्‍पर्श करें"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"शब्‍दकोश उपलब्‍ध है"</string>
@@ -163,7 +164,7 @@
     <string name="install_dict" msgid="180852772562189365">"इंस्टॉल करें"</string>
     <string name="cancel_download_dict" msgid="7843340278507019303">"रद्द करें"</string>
     <string name="delete_dict" msgid="756853268088330054">"हटाएं"</string>
-    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"आपके मोबाइल पर चयनित भाषा के लिए शब्‍दकोश उपलब्‍ध है.&lt;br/&gt; हम आपके लेखन अनुभव को बेहतर बनाने के लिए <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> शब्‍दकोश &lt;b&gt;डाउनलोड करने&lt;/b&gt; की अनुशंसा करते हैं.&lt;br/&gt; &lt;br/&gt; 3G में डाउनलोड करने पर एक या दो मिनट लगेंगे. यदि आपके पास &lt;b&gt;असीमित डेटा योजना&lt;/b&gt; नहीं है, तो शुल्क लागू हो सकते हैं.&lt;br/&gt; यदि आप अपनी डेटा योजना के बारे में सुनिश्चित नहीं हैं, तो हम अपने आप डाउनलोड प्रारंभ करने के लिए वाई-फ़ाई  कनेक्‍शन ढूंढने की अनुशंसा करते हैं.&lt;br/&gt; &lt;br/&gt; युक्ति: आप अपने मोबाइल उपकरण के &lt;b&gt;सेटिंग&lt;/b&gt; मेनू में &lt;b&gt;भाषा और इनपुट&lt;/b&gt; पर जाकर शब्‍दकोशों को डाउनलोड कर सकते हैं और निकाल सकते हैं."</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"आपके मोबाइल पर चयनित भाषा के लिए शब्‍दकोश उपलब्‍ध है.&lt;br/&gt; हम आपके लेखन अनुभव को बेहतर बनाने के लिए <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> शब्‍दकोश &lt;b&gt;डाउनलोड करने&lt;/b&gt; की सुझाव देते हैं.&lt;br/&gt; &lt;br/&gt; 3G में डाउनलोड करने पर एक या दो मिनट लगेंगे. यदि आपके पास &lt;b&gt;असीमित डेटा योजना&lt;/b&gt; नहीं है, तो शुल्क लागू हो सकते हैं.&lt;br/&gt; यदि आप अपनी डेटा योजना के बारे में सुनिश्चित नहीं हैं, तो हम अपने आप डाउनलोड प्रारंभ करने के लिए वाई-फ़ाई  कनेक्‍शन ढूंढने की सुझाव देते हैं.&lt;br/&gt; &lt;br/&gt; युक्ति: आप अपने मोबाइल उपकरण के &lt;b&gt;सेटिंग&lt;/b&gt; मेनू में &lt;b&gt;भाषा और इनपुट&lt;/b&gt; पर जाकर शब्‍दकोशों को डाउनलोड कर सकते हैं और निकाल सकते हैं."</string>
     <string name="download_over_metered" msgid="1643065851159409546">"अभी डाउनलोड करें (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
     <string name="do_not_download_over_metered" msgid="2176209579313941583">"वाई-फ़ाई  से डाउनलोड करें"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> के लिए एक शब्‍दकोश उपलब्‍ध है"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 5206c7f..28ec9f6 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nije omogućen nijedan način glasovnog unosa. Provjerite postavke jezika i unosa."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguriraj načine ulaza"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Jezici unosa"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Slanje povratnih informacija"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Jezici unosa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dodirnite ponovo za spremanje"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Rječnik je dostupan"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 272249b..368deab 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nincs engedélyezett hangbeviteli módszer. Nézze meg a Nyelvi és beviteli beállításokat."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Beviteli módok beállítása"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Beviteli nyelvek"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Visszajelzés küldése"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Beviteli nyelvek"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Érintse meg újból a mentéshez"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Van elérhető szótár"</string>
diff --git a/java/res/values-hy-rAM/strings.xml b/java/res/values-hy-rAM/strings.xml
index f858c52..f0742b4 100644
--- a/java/res/values-hy-rAM/strings.xml
+++ b/java/res/values-hy-rAM/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ձայնային ներածման որևէ եղանակ միացված չէ։ Ստուգեք Լեզվի և ներածման կարգավորումները։"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Կարգավորել մուտքագրման մեթոդները"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Մուտքագրման լեզուներ"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Արձագանքել"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Մուտքագրման լեզուներ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Պահպանելու համար կրկին հպեք"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Բառարանն առկա է"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index d693461..f9353d0 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Tidak ada metode masukan suara yang diaktifkan. Periksa setelan Bahasan &amp; masukan."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan metode masukan"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Bahasa masukan"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Kirim masukan"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus yang tersedia"</string>
diff --git a/java/res/values-is-rIS/strings.xml b/java/res/values-is-rIS/strings.xml
index df802ff..ecf9705 100644
--- a/java/res/values-is-rIS/strings.xml
+++ b/java/res/values-is-rIS/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Engar innsláttaraðferðir fyrir rödd virkar. Kannaðu stillingar tungumáls og innsláttar."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Stilla innsláttaraðferðir"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Innsláttartungumál"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Senda inn álit"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Innsláttartungumál"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Snertu aftur til að vista"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Orðabók í boði"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 8230020..4f81588 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nessun metodo di immissione vocale abilitato. Controlla le impostazioni Lingua e input."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configura metodi di immissione"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Lingue comandi"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Invia feedback"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Guida e feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Lingue comandi"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tocca di nuovo per salvare"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index baf0eab..ed34165 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"לא הופעלו שיטות של קלט קולי. בדוק את הגדרות השפה והקלט."</string>
     <string name="configure_input_method" msgid="373356270290742459">"הגדרת שיטות קלט"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"שפות קלט"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"שלח משוב"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"שפות קלט"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"גע שוב כדי לשמור"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"מילון זמין"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 53436ad..77e0fa0 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"有効になっている音声入力方法がありません。[言語と入力]設定をご確認ください。"</string>
     <string name="configure_input_method" msgid="373356270290742459">"入力方法を設定"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"入力言語"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"フィードバックを送信"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"入力言語"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"保存するにはもう一度タップ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"辞書を利用できます"</string>
diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml
index f30de57..7e05e5f 100644
--- a/java/res/values-ka-rGE/strings.xml
+++ b/java/res/values-ka-rGE/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ხმოვანი შეყვანის მეთოდები ჩართული არ არის. შეამოწმეთ ენის &amp; შეყვანის პარამეტრები."</string>
     <string name="configure_input_method" msgid="373356270290742459">"შეყვანის მეთოდების კონფიგურაცია"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"შეყვანის ენები"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"უკუკავშირის გაგზავნა"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"შეყვანის ენები"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"შეეხეთ ისევ შესანახად"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ხელმისაწვდომია ლექსიკონი"</string>
diff --git a/java/res/values-kk-rKZ/strings.xml b/java/res/values-kk-rKZ/strings.xml
index 097c7e0..e08fd78 100644
--- a/java/res/values-kk-rKZ/strings.xml
+++ b/java/res/values-kk-rKZ/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Дауыспен енгізу әдістері қосылмаған. «Тіл және енгізу параметрлері» тармағын тексеріңіз."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Енгізу әдістерін теңшеу"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Енгізу тілдері"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Кері байланыс жіберу"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Енгізу тілдері"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Сақтау үшін қайта түртіңіз"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Сөздік қолжетімді"</string>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 479adab..2078128 100644
--- a/java/res/values-km-rKH/strings.xml
+++ b/java/res/values-km-rKH/strings.xml
@@ -38,7 +38,7 @@
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"បង្ហាញ​នៅ​ពេល​ដែល​បើក​ភាសា​បញ្ចូល​ច្រើន"</string>
     <string name="sliding_key_input_preview" msgid="6604262359510068370">"បង្ហាញ​ទ្រនិច​បង្ហាញ​ស្លាយ"</string>
     <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"បង្ហាញ​​សញ្ញា​មើល​​ឃើញ​ខណៈ​ពេល​ដែល​រុញ​ពី​ឆ្វេង ឬ​​គ្រាប់​ចុច​​និមិត្ត​សញ្ញា"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល​"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"គ្មាន​ការ​ពន្យារពេល"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"លំនាំដើម"</string>
     <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> មិល្លី​វិនាទី"</string>
@@ -49,7 +49,7 @@
     <string name="enable_metrics_logging" msgid="5506372337118822837">"ធ្វើឲ្យ <xliff:g id="APPLICATION_NAME">%s</xliff:g> ប្រសើរ​ឡើង"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"រយៈ​ពេល​ចុច​ដកឃ្លា​ពីរដង"</string>
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"ប៉ះ​ដកឃ្លា​ពីរ​​ដង​បញ្ចូល​​​រយៈ​ពេល​ដែល​អនុវត្ត​តាម​ដកឃ្លា"</string>
-    <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ"</string>
+    <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ​"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"សរសេរ​ពាក្យ​ដំបូង​​​ជា​អក្សរ​ធំ​​នៃ​ប្រយោគ​នីមួយ​ៗ"</string>
     <string name="edit_personal_dictionary" msgid="3996910038952940420">"វចនានុក្រម​ផ្ទាល់ខ្លួន"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
@@ -57,7 +57,7 @@
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"បង្ហាញ​ការ​ស្នើ​​កែ"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"បង្ហាញ​ពាក្យ​​បាន​​ផ្ដល់​​ស្នើ​​ខណៈ​ពេល​​​វាយ​បញ្ចូល"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"ទប់ស្កាត់​​ពាក្យ​​បំពាន"</string>
-    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"កុំ​ស្នើ​ឲ្យ​ពាក្យ​បំពាន​មាន​សក្ដានុពល"</string>
+    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"កុំ​ស្នើ​ឲ្យ​ពាក្យ​បំពាន​មាន​សក្ដានុពល​"</string>
     <string name="auto_correction" msgid="7630720885194996950">"ការ​កែ​​​ស្វ័យប្រវត្តិ"</string>
     <string name="auto_correction_summary" msgid="5625751551134658006">"ចន្លោះ​មិន​ឃើញ ​និង​សញ្ញា​​វណ្ណយុត្ត​កែ​ពាក្យ​ដែល​បាន​វាយ​ខុស​ស្វ័យប្រវត្តិ"</string>
     <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"បិទ"</string>
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"គ្មាន​វិធីសាស្ត្រ​បញ្ចូល​សំឡេង​បាន​បើក។ ពិនិត្យ​មើល​ការ​កំណត់​ភាសា &amp; ការ​បញ្ចូល។"</string>
     <string name="configure_input_method" msgid="373356270290742459">"កំណត់​រចនាសម្ព័ន្ធ​វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"បញ្ចូល​ភាសា"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ផ្ញើ​មតិ​អ្នក​ប្រើ"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"​​បញ្ចូល​ភាសា"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ប៉ះ​ម្ដង​ទៀត​ ដើម្បី​រក្សា​ទុក"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"មាន​វចនានុក្រម"</string>
@@ -115,7 +116,7 @@
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"ថិរវេលា​​ញ័រ​​ពេល​ចុច​គ្រាប់ចុច"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"កម្រិត​សំឡេង​ពេល​ចុច​គ្រាប់​ចុច"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"អាន​ឯកសារ​វចនានុក្រម​ខាង​ក្រៅ"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"គ្មាន​ឯកសារ​វចនានុក្រម​នៅ​ក្នុង​ថត​ទាញ​យក"</string>
+    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"គ្មាន​ឯកសារ​វចនានុក្រម​នៅ​ក្នុង​ថត​ទាញ​យក​​"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"ជ្រើស​ឯកសារ​វចនានុក្រម​ ដើម្បី​ដំឡើង"</string>
     <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"ពិត​ជា​ដំឡើង​ឯកសារ​នេះ​សម្រាប់ <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
     <string name="error" msgid="8940763624668513648">"មាន​កំហុស"</string>
@@ -142,7 +143,7 @@
     <string name="dictionary_provider_name" msgid="3027315045397363079">"កម្មវិធី​ផ្ដល់​វចនានុក្រម"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"សេវាកម្ម​​វចនានុក្រម"</string>
     <string name="download_description" msgid="6014835283119198591">"ព័ត៌មាន​បច្ចុប្បន្នភាព​វចនានុក្រម"</string>
-    <string name="dictionary_settings_title" msgid="8091417676045693313">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"ផ្នែក​បន្ថែម​វចនានុក្រម​​"</string>
     <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"វចនានុក្រម​​​​​អាច​ប្រើ​បាន"</string>
     <string name="dictionary_settings_summary" msgid="5305694987799824349">"ការ​កំណត់​សម្រាប់​វចនានុក្រម"</string>
     <string name="user_dictionaries" msgid="3582332055892252845">"វចនានុក្រម​​​អ្នក​ប្រើ"</string>
@@ -158,10 +159,10 @@
     <string name="message_updating" msgid="4457761393932375219">"ពិនិត្យមើល​បច្ចុប្បន្នភាព"</string>
     <string name="message_loading" msgid="5638680861387748936">"កំពុង​ផ្ទុក..."</string>
     <string name="main_dict_description" msgid="3072821352793492143">"វចនានុក្រម​ចម្បង"</string>
-    <string name="cancel" msgid="6830980399865683324">"បោះ​បង់"</string>
+    <string name="cancel" msgid="6830980399865683324">"បោះ​បង់​"</string>
     <string name="go_to_settings" msgid="3876892339342569259">"ការ​កំណត់"</string>
     <string name="install_dict" msgid="180852772562189365">"ដំឡើង"</string>
-    <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់​"</string>
     <string name="delete_dict" msgid="756853268088330054">"លុប"</string>
     <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"ភាសា​ដែល​បាន​ជ្រើស​នៅ​លើ​ឧបករណ៍​ចល័ត​មាន​វចនានុក្រម​អាច​ប្រើ​បាន។&lt;br/&gt; យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ &lt;b&gt;ទាញ​យក&lt;/b&gt; វចនានុក្រម​ភាសា <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> ដើម្បី​បង្កើន​បទពិសោធន៍​វាយ​បញ្ចូល​របស់​អ្នក។&lt;br/&gt; &lt;br/&gt; ការ​ទាញ​យក​អាច​ចំណាយ​ពេល​ប្រហែល​ពីរ​នាទី​នៅ​តាម 3G។ ការ​គិត​ថ្លៃ​អាច​អនុវត្ត​ប្រសិន​បើ​អ្នក​មិន​ប្រើ &lt;b&gt;ផែនការ​ទិន្នន័យ​គ្មាន​ដែន​កំណត់&lt;/b&gt;.&lt;br/&gt; បើ​អ្នក​មិន​ប្រាកដ​​ថា​ផែនការ​ណា​មួយ​ដែល​អ្នក​មាន យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ​​ភ្ជាប់​វ៉ាយហ្វាយ ដើម្បី​ចាប់ផ្ដើម​ទាញ​យក​ដោយ​ស្វ័យ​ប្រវត្តិ។&lt;br/&gt; &lt;br/&gt; ជំនួយ៖ អ្នក​អាច​ទាញ​យក និង​លុប​វចនានុក្រម​ដោយ​ចូល​ទៅ​ &lt;b&gt;ភាសា &amp; ការ​បញ្ចូល&lt;/b&gt; នៅ​ក្នុង​ម៉ឺនុយ &lt;b&gt;ការ​កំណត់&lt;/b&gt; សម្រាប់​ឧបករណ៍​ចល័ត។"</string>
     <string name="download_over_metered" msgid="1643065851159409546">"ទាញ​យក​ឥឡូវ​នេះ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> មេកាបៃ)"</string>
@@ -179,7 +180,7 @@
     <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"ពាក្យ៖"</string>
     <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"ផ្លូវកាត់​៖"</string>
     <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"ភាសា៖"</string>
-    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ"</string>
+    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ​"</string>
     <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"ផ្លូវកាត់​ជា​ជម្រើស"</string>
     <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"កែ​ពាក្យ"</string>
     <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"កែ"</string>
diff --git a/java/res/values-kn-rIN/strings.xml b/java/res/values-kn-rIN/strings.xml
index 30e595c..92c39f3 100644
--- a/java/res/values-kn-rIN/strings.xml
+++ b/java/res/values-kn-rIN/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ಯಾವುದೇ ಧ್ವನಿ ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿಲ್ಲ. ಭಾಷೆ &amp; ಇನ್‌ಪುಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ."</string>
     <string name="configure_input_method" msgid="373356270290742459">"ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳನ್ನು ಕಾನ್ಫಿಗರ್ ಮಾಡಿ"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ಇನ್‌ಪುಟ್ ಭಾಷೆಗಳು"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸಿ"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"ಇನ್‌ಪುಟ್ ಭಾಷೆಗಳು"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ಉಳಿಸಲು ಮತ್ತೆ ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ನಿಘಂಟು ಲಭ್ಯವಿದೆ"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 5f51fcd..29d7aa7 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"사용 설정된 음성 입력 방법이 없습니다. 언어 및 입력 설정을 확인하세요."</string>
     <string name="configure_input_method" msgid="373356270290742459">"입력 방법 설정"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"입력 언어"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"의견 보내기"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"입력 언어"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"저장하려면 다시 터치"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"사전 사용 가능"</string>
diff --git a/java/res/values-ky-rKG/strings.xml b/java/res/values-ky-rKG/strings.xml
index 8de9c10..7054e3f 100644
--- a/java/res/values-ky-rKG/strings.xml
+++ b/java/res/values-ky-rKG/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Үн менен киргизүү ыкмаларынын бири да иштетилген эмес. Тил &amp; киргизүү жөндөөлөрүн текшериңиз."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Дайндрд киргзүү ыкмалрн конфигрцлоо"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Киргизүү тилдери"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Жооп пикир жөнөтүү"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Киргизүү тилдери"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Сактоо үчүн кайра тийип коюңуз"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Сөздүк бар"</string>
diff --git a/java/res/values-lo-rLA/strings.xml b/java/res/values-lo-rLA/strings.xml
index 2407c3b..eed5380 100644
--- a/java/res/values-lo-rLA/strings.xml
+++ b/java/res/values-lo-rLA/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ບໍ່ມີວິທີການປ້ອນສຽງເປີດນໍາໃຊ້. ໃຫ້ກວດເບິ່ງການຕັ້ງຄ່າໃນເມນູ ພາສາ &amp; ການປ້ອນຂໍ້ມູນ."</string>
     <string name="configure_input_method" msgid="373356270290742459">"ຕັ້ງຄ່າຮູບແບບການປ້ອນຂໍ້ມູນ"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ພາສາການປ້ອນຂໍ້ມູນ"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ສົ່ງຄຳຕິຊົມ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"ຊ່ວຍ​ເຫຼືອ &amp; ຄຳ​ຕິ​ຊົມ"</string>
     <string name="select_language" msgid="3693815588777926848">"ພາສາການປ້ອນຂໍ້ມູນ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ກົດອີກຄັ້ງເພື່ອບັນທຶກ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ມີວັດຈະນານຸກົມ"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index d207f7b..c1ef8aa 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nėra jokių įgalintų įvesties balsu metodų. Patikrinkite kalbos ir įvesties nustatymus."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigūruoti įvesties metodus"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Įvesties kalbos"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Siųsti atsiliepimą"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Pagalba ir atsiliepimai"</string>
     <string name="select_language" msgid="3693815588777926848">"Įvesties kalbos"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Jei norite išsaugoti, palieskite dar kartą"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Žodynas galimas"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 9cff149..218300e 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nav iespējota neviena balss ievades metode. Pārbaudiet valodas un ievades iestatījumus."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Ievades metožu konfigurēšana"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Ievades valodas"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Sūtīt atsauksmes"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Ievades valodas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pieskarieties vēlreiz, lai saglabātu."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ir pieejama vārdnīca."</string>
diff --git a/java/res/values-mk-rMK/strings.xml b/java/res/values-mk-rMK/strings.xml
index 9cae531..dd10f07 100644
--- a/java/res/values-mk-rMK/strings.xml
+++ b/java/res/values-mk-rMK/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Не се овозможени методи за гласовно внесување. Проверете ги поставките за Јазик и внесување."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Конфигурирај методи на влез"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Влезни јазици"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Испрати повратни информации"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Влезни јазици"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Допрете повторно за да се зачува"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Речникот е достапен"</string>
diff --git a/java/res/values-ml-rIN/strings.xml b/java/res/values-ml-rIN/strings.xml
index cffb6a1..69d56bd 100644
--- a/java/res/values-ml-rIN/strings.xml
+++ b/java/res/values-ml-rIN/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"വോയ്‌സ് ടൈപ്പുചെയ്യൽ രീതികളൊന്നും പ്രവർത്തനക്ഷമമല്ല. ഭാഷ &amp; ടൈപ്പു ചെയ്യൽ ക്രമീകരണങ്ങൾ പരിശോധിക്കുക."</string>
     <string name="configure_input_method" msgid="373356270290742459">"ടൈപ്പുചെയ്യൽ രീതികൾ കോൺഫിഗർ ചെയ്യുക"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ടൈപ്പുചെയ്യൽ ഭാഷകൾ"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ഫീഡ്‍ബാക്ക് അയയ്ക്കുക"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"ടൈപ്പുചെയ്യൽ ഭാഷകൾ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"സംരക്ഷിക്കുന്നതിനായി വീണ്ടും സ്‌പർശിക്കുക"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"നിഘണ്ടു ലഭ്യമാണ്"</string>
diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml
index d0982d8..db04f60 100644
--- a/java/res/values-mn-rMN/strings.xml
+++ b/java/res/values-mn-rMN/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ямар ч дуу оруулах хэрэглүүр идэвхжээгүй байна. Хэл болон оруулалтын тохиргоог шалгана уу."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Оруулах аргуудын тохиргоо"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Оруулах хэл"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Санал хүсэлт илгээх"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Тусламж &amp; санал хүсэлт"</string>
     <string name="select_language" msgid="3693815588777926848">"Оруулах хэл"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Хадгалахын тулд дахин хүрнэ үү"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Толь бичиг байна"</string>
diff --git a/java/res/values-mr-rIN/strings.xml b/java/res/values-mr-rIN/strings.xml
index c9365ec..9323c71 100644
--- a/java/res/values-mr-rIN/strings.xml
+++ b/java/res/values-mr-rIN/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"व्हॉइस इनपुट पद्धती सक्षम केल्या नाहीत. भाषा आणि इनपुट सेटिंग्ज तपासा."</string>
     <string name="configure_input_method" msgid="373356270290742459">"इनपुट पद्धती कॉन्फिगर करा"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"इनपुट भाषा"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"अभिप्राय पाठवा"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"इनपुट भाषा"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"जतन करण्यासाठी पुन्हा स्पर्श करा"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"शब्दकोश उपलब्ध"</string>
diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml
index e61ff09..78cdd0d 100644
--- a/java/res/values-ms-rMY/strings.xml
+++ b/java/res/values-ms-rMY/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Tiada kaedah input suara didayakan. Semak Bahasa &amp; tetapan input."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan kaedah input"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Bahasa input"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Hantar maklum balas"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Bahasa input"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus tersedia"</string>
diff --git a/java/res/values-my-rMM/strings-action-keys.xml b/java/res/values-my-rMM/strings-action-keys.xml
index f7a2ca9..d15c9e5 100644
--- a/java/res/values-my-rMM/strings-action-keys.xml
+++ b/java/res/values-my-rMM/strings-action-keys.xml
@@ -27,5 +27,5 @@
     <string name="label_send_key" msgid="482252074224462163">"ပို့ရန်"</string>
     <string name="label_search_key" msgid="7965186050435796642">"ရှာဖွေရန်"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"ဆိုင်းငံ့ရန်"</string>
-    <string name="label_wait_key" msgid="5891247853595466039">"စောင့်ဆိုင်းရန်"</string>
+    <string name="label_wait_key" msgid="5891247853595466039">"စောင့်ဆိုင်းရန်"</string>
 </resources>
diff --git a/java/res/values-my-rMM/strings.xml b/java/res/values-my-rMM/strings.xml
index 478beb7..37d99d6 100644
--- a/java/res/values-my-rMM/strings.xml
+++ b/java/res/values-my-rMM/strings.xml
@@ -31,7 +31,7 @@
     <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"ဘာသာများစွာ ရွေးချယ်မှု"</string>
     <string name="settings_screen_gesture" msgid="9113437621722871665">"အမူယာစာရိုက်ခြင်း စိတ်ကြိုက်များ"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"စာအမှားပြပြင်ခြင်း"</string>
-    <string name="settings_screen_advanced" msgid="7472408607625972994">"အဆင့်မြင့်"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"အဆင့်မြင့်"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"အခြားထည့်သွင်းမည့် နည်းလမ်းများသို့ ပြောင်းရန်"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"ဘာသာပြောင်းသည့် ကီးသည် အခြားထည့်သွင်းရန် နည်းလမ်းများလည်း ပါဝင်သည်"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"ဘာသာစကား ပြောင်းခလုတ်"</string>
@@ -46,7 +46,7 @@
     <string name="use_contacts_dict" msgid="4435317977804180815">"အဆယ်ကသွယ်အမည်များ အကြံပြုမည်"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"အကြံပြုချက်များနှင့် အမှားပြင်ခြင်းများအတွက် အဆက်သွယ်မှ အမည်များ အသုံးပြုမည်"</string>
     <string name="use_personalized_dicts" msgid="5167396352105467626">"ကိုယ်ရေးကိုယ်တာ အကြံပြုချက်များ"</string>
-    <string name="enable_metrics_logging" msgid="5506372337118822837">"မြှင့်တင်ပါ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="enable_metrics_logging" msgid="5506372337118822837">"မြှင့်တင်ပါ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"နှစ်နေရာခြား အဆုံးသတ်"</string>
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"အချိန်ကာလ"</string>
     <string name="auto_cap" msgid="1719746674854628252">"အော်တိုစာလုံးကြီးပြောင်း"</string>
@@ -76,9 +76,9 @@
     <string name="voice_input" msgid="3583258583521397548">"အသံထည့်သွင်းရန် ခလုတ်"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"မည်သည့် Check Language &amp; input settings."</string>
     <string name="configure_input_method" msgid="373356270290742459">"ထည့်သွင်းရန် နည်းလမ်းကို ပြုပြင်မည်"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"ထည့်သွင်းမှု ဘာသာ"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"တုံ့ပြန်ချက် ပို့ရန်"</string>
-    <string name="select_language" msgid="3693815588777926848">"ထည့်သွင်းမှု ဘာသာ"</string>
+    <string name="language_selection_title" msgid="1651299598555326750">"ထည့်သွင်းမှု ဘာသာ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"အကူအညီ &amp; တုံ့ပြန်ချက်"</string>
+    <string name="select_language" msgid="3693815588777926848">"ထည့်သွင်းမှု ဘာသာ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"သိမ်းရန် နောက်တစ်ကြိမ်နှိပ်ပါ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"အဘိဓါန်ရနိုင်"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ကီးဘုတ်အရောင်"</string>
@@ -149,7 +149,7 @@
     <string name="default_user_dict_pref_name" msgid="1625055720489280530">"သုံးစွဲသူ၏ အဘိဓာန်"</string>
     <string name="dictionary_available" msgid="4728975345815214218">"အဘိဓါန်ရရှိနိုင်"</string>
     <string name="dictionary_downloading" msgid="2982650524622620983">"လက်ရှိ ဒေါင်းလုပ်လုပ်နေသည်"</string>
-    <string name="dictionary_installed" msgid="8081558343559342962">"ထည့်သွင်းပြီး"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"ထည့်သွင်းပြီး"</string>
     <string name="dictionary_disabled" msgid="8950383219564621762">"ထည့်သွင်းထားပြီး၊ ပိတ်ထားသည်"</string>
     <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"အဘိဓါန်ဝန်ဆောင်မှုသို့ ချိတ်ဆက်ရန် ပြဿနာရှိနေသည်"</string>
     <string name="no_dictionaries_available" msgid="8039920716566132611">"အဘိဓါန်မရှိ"</string>
@@ -163,7 +163,7 @@
     <string name="install_dict" msgid="180852772562189365">"တပ်ဆင်ပါ"</string>
     <string name="cancel_download_dict" msgid="7843340278507019303">"ပယ်ဖျက်ရန်"</string>
     <string name="delete_dict" msgid="756853268088330054">"ဖျက်ရန်"</string>
-    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"သင့်ဖုန်းရှိ ရွေးချယ်ထားသည့် ဘာသာအတွက် အဘိဓါန်ရှိပါသည်။ &lt;br/&gt; အဘိဓါန်အား &lt;b&gt;ဒေါင်းလုပ်လုပ်ကာ&lt;/b&gt; the <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>  သင့်စာရိုက် အတွေ့အကြုံတိုးတက်စေရန် ကျွန်ုပ်တို့အကြံပြုပါသည်။ &lt;br/&gt; &lt;br/&gt; ဒေါင်းလုပ်လုပ်ရန် 3G ပေါ်တွင် ၁ မှ ၂ မိနစ်ခန့်ကြာနိုင်သည်။ သင့်တွင် &lt;b&gt;အကန့်သတ်မှရိ အချက်လက် သုံးစွဲမှု&lt;/b&gt;မရှိလျှင် ငွေကျသင့်နိုင်ပါသည်။ &lt;br/&gt; သင့်တွင် မည်သည့်အချက်လက်သုံးစွဲမှု ရှိနေသည်ကိုမသိလျှင်၊ အလိုအလျောက် ဒေါင်းလုပ်လုပ်ရန် Wi-Fi ကွန်ရက်တစ်ခု ရှာဖွေရန် တိုက်တွန်းပါသည်။ &lt;br/&gt; &lt;br/&gt; နည်းလမ်း: သင့်ဖုန်းကိရိယာရှိ &lt;b&gt;ဆက်တင်ထဲတွင်&lt;/b&gt; &lt;b&gt;ဘာသာ &amp; ထည့်သွင်းမှု&lt;/b&gt; သို့သွားကာ အဘိဓါန်များကို ဒေါင်းလုပ်လုပ်နိုင် ဖယ်ရှားနိုင်ပါသည်။"</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"သင့်ဖုန်းရှိ ရွေးချယ်ထားသည့် ဘာသာအတွက် အဘိဓါန်ရှိပါသည်။ &lt;br/&gt; အဘိဓါန်အား &lt;b&gt;ဒေါင်းလုပ်လုပ်ကာ&lt;/b&gt; the <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>  သင့်စာရိုက် အတွေ့အကြုံတိုးတက်စေရန် ကျွန်ုပ်တို့အကြံပြုပါသည်။ &lt;br/&gt; &lt;br/&gt; ဒေါင်းလုပ်လုပ်ရန် 3G ပေါ်တွင် ၁ မှ ၂ မိနစ်ခန့်ကြာနိုင်သည်။ သင့်တွင် &lt;b&gt;အကန့်သတ်မှရိ အချက်လက် သုံးစွဲမှု&lt;/b&gt;မရှိလျှင် ငွေကျသင့်နိုင်ပါသည်။ &lt;br/&gt; သင့်တွင် မည်သည့်အချက်လက်သုံးစွဲမှု ရှိနေသည်ကိုမသိလျှင်၊ အလိုအလျောက် ဒေါင်းလုပ်လုပ်ရန် Wi-Fi ကွန်ရက်တစ်ခု ရှာဖွေရန် တိုက်တွန်းပါသည်။ &lt;br/&gt; &lt;br/&gt; နည်းလမ်း: သင့်ဖုန်းကိရိယာရှိ &lt;b&gt;ဆက်တင်ထဲတွင်&lt;/b&gt; &lt;b&gt;ဘာသာ &amp; ထည့်သွင်းမှု&lt;/b&gt; သို့သွားကာ အဘိဓါန်များကို ဒေါင်းလုပ်လုပ်နိုင် ဖယ်ရှားနိုင်ပါသည်။"</string>
     <string name="download_over_metered" msgid="1643065851159409546">"ယခုဒေါင်းလုပ်လုပ်မည် (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
     <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi အသုံးပြု၍ ဒေါင်းလုပ်လုပ်ရန်"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> အတွက် အဘိဓါန် ရနိုင်ပါသည်"</string>
@@ -184,7 +184,7 @@
     <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"စာလုံးကို ပြင်ဆင်မည်"</string>
     <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"တည်းဖြတ်ရန်"</string>
     <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"ဖျက်ရန်"</string>
-    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"သင့်အဘိဓာန်ထဲတွင် မည်သည့်စာလုံးမှမရှိပါ။ ထပ်ထည့်ခြင်း(+)ခလုတ်ကို ထိ၍ စာလုံးထည့်ပါ။"</string>
+    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"သင့်အဘိဓာန်ထဲတွင် မည်သည့်စာလုံးမှမရှိပါ။ ထပ်ထည့်ခြင်း(+)ခလုတ်ကို ထိ၍ စာလုံးထည့်ပါ။"</string>
     <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"ဘာသာစကားအားလုံးအတွက်"</string>
     <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"ဘာသာစကားပိုများများ…"</string>
     <string name="user_dict_settings_delete" msgid="110413335187193859">"ဖျက်သိမ်းရန်"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 480e705..c307286 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ingen taleinndatametoder er aktivert. Sjekk Språk og inndata-innstillingene."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inndatametoder"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Inndataspråk"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send tilbakemelding"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Inndataspråk"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Trykk på nytt for å lagre"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string>
diff --git a/java/res/values-ne-rNP/strings.xml b/java/res/values-ne-rNP/strings.xml
index 8f1afdc..291b08f 100644
--- a/java/res/values-ne-rNP/strings.xml
+++ b/java/res/values-ne-rNP/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"कुनै आवाज इनपुट विधिहरू सक्षम गरिएका छैनन्। भाषा र इनपुट सेटिङहरूको जाँच गर्नुहोस्।"</string>
     <string name="configure_input_method" msgid="373356270290742459">"इनपुट विधिहरू कन्फिगर गर्नुहोस्"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"इनपुट भाषाहरू"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"प्रतिक्रिया पठाउनुहोस्"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"इनपुट भाषाहरू"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"बचत गर्न पुनः छुनुहोस्"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"उपलब्ध शब्दकोश"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index b4c7049..6a391e7 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Geen spraakinvoermethoden ingeschakeld. Ga naar \'Instellingen voor taal en invoer\'."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Invoermethoden configureren"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Invoertalen"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Feedback verzenden"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Invoertalen"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak nogmaals aan om op te slaan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 0cf66c7..ada0134 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nie włączono żadnych metod wprowadzania głosowego. Sprawdź ustawienia języka i wprowadzania."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguruj metody wprowadzania"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Języki wprowadzania"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Prześlij opinię"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Języki wprowadzania"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotknij ponownie, aby zapisać"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Słownik dostępny"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index b4a3f3e..5707057 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nenhum método de entrada de texto por voz ativado. Verifique as definições de Idioma e introdução."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introdução"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Idiomas de introdução"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 0b42f89..16420c4 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nenhum método de entrada de texto por voz ativado. Verifique as configurações \"Idioma e entrada\"."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para salvar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 4ac0c15..67b1eef 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nicio metodă de intrare vocală activată. Verificați setările pentru limbă și introducere de text."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configuraţi metodele de intrare"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Selectaţi limba"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Trimiteți feedback"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Limbi de introducere de text"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Atingeţi din nou pentru a salva"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicţionar disponibil"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 42ca338..7487fe5 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Голосовой способ ввода не включен. Проверьте раздел настроек \"Язык и ввод\"."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Настройка способов ввода"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Языки ввода"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Отправить отзыв"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Языки ввода"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Нажмите, чтобы сохранить"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Доступен словарь"</string>
diff --git a/java/res/values-si-rLK/strings.xml b/java/res/values-si-rLK/strings.xml
index 1be805c..034f3cd 100644
--- a/java/res/values-si-rLK/strings.xml
+++ b/java/res/values-si-rLK/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"හඬ ආදාන සබල කර නැත. භාෂාව සහ ආදාන සැකසීම් පරීක්ෂා කරන්න."</string>
     <string name="configure_input_method" msgid="373356270290742459">"ආදාන ක්‍රම වින්‍යාස කරන්න"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ආදාන භාෂා"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ප්‍රතිපෝෂණ යවන්න"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"ආදාන භාෂා"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"සුරැකීමට නැවත ස්පර්ශ කරන්න"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ශබ්ද කෝෂය ලබාගත හැක"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 859cc03..2728c37 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nie sú povolené žiadne metódy hlasového vstupu. Skontrolujte nastavenia položky Jazyk a vstup."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurovať metódy vstupu"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Jazyky vstupu"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Odoslať spätnú väzbu"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opätovným dotykom uložíte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"K dispozícii je slovník"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index 72ee320..9b15cc3 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ni omogočenih glasovnih načinov vnosa. Preverite nastavitve v razdelku »Jezik in vnos«."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Nastavitev načinov vnosa"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Jeziki vnosa"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Pošljite povratne informacije"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Jeziki vnosa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotaknite se še enkrat, da shranite"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovar je na voljo"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 9a9d27e..6739fcf 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ниједан метод гласовног уноса није омогућен. Проверите Подешавања језика и уноса."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Конфигурисање метода уноса"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Језици за унос"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Пошаљи повратне информације"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Језици уноса"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Поново додирните да бисте сачували"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Речник је доступан"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index fe1d776..1c090e2 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ingen röstinmatningsmetod har aktiverats. Kontrollera språk- och inmatningsinställningarna."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurera inmatningsmetoder"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Inmatningsspråk"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Skicka feedback"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Inmatningsspråk"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Spara genom att trycka igen"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"En ordlista är tillgänglig"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 816c3af..f5b8dcb 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Hakuna mbinu ya kuweka data kwa kutamka iliyowashwa. Angalia Lugha na mipangilio ya kuingiza data."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Sanidi mbinu za uingizaji"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Lugha za uingizaji"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Tuma maoni"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Usaidizi na maoni"</string>
     <string name="select_language" msgid="3693815588777926848">"Lugha zinazoruhusiwa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gusa tena ili kuhifadhi"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamusi inapatikana"</string>
diff --git a/java/res/values-ta-rIN/strings.xml b/java/res/values-ta-rIN/strings.xml
index 8ab0c5b..0f0f142 100644
--- a/java/res/values-ta-rIN/strings.xml
+++ b/java/res/values-ta-rIN/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"குரல் உள்ளீட்டு முறைகள் எதுவும் இயக்கப்படவில்லை. மொழி &amp; உள்ளீட்டு அமைப்புகளைச் சரிபார்க்கவும்."</string>
     <string name="configure_input_method" msgid="373356270290742459">"உள்ளீட்டு முறைகளை உள்ளமைத்தல்"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"உள்ளீட்டு மொழிகள்"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"கருத்தை அனுப்பு"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"உள்ளீட்டு மொழிகள்"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"சேமிக்க தொடவும்"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"அகராதி உள்ளது"</string>
diff --git a/java/res/values-te-rIN/strings.xml b/java/res/values-te-rIN/strings.xml
index 0023557..4e92d1b 100644
--- a/java/res/values-te-rIN/strings.xml
+++ b/java/res/values-te-rIN/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"వాయిస్ ఇన్‌పుట్ పద్ధతులు ఏవీ ప్రారంభించబడలేదు. భాష &amp; ఇన్‌పుట్ సెట్టింగ్‌లను తనిఖీ చేయండి."</string>
     <string name="configure_input_method" msgid="373356270290742459">"ఇన్‌పుట్ పద్ధతులను కాన్ఫిగర్ చేయండి"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ఇన్‌పుట్ భాషలు"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"అభిప్రాయాన్ని పంపండి"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"ఇన్‌పుట్ భాషలు"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"సేవ్ చేయడానికి మళ్లీ తాకండి"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"నిఘంటువు అందుబాటులో ఉంది"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index cb59cd2..f69c63c 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ไม่ได้เปิดใช้วิธีการป้อนข้อมูลด้วยเสียง ตรวจสอบภาษาและการตั้งค่าการป้อนข้อมูล"</string>
     <string name="configure_input_method" msgid="373356270290742459">"กำหนดค่าวิธีการป้อนข้อมูล"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ภาษาในการป้อนข้อมูล"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"ส่งข้อเสนอแนะ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"ความช่วยเหลือและความคิดเห็น"</string>
     <string name="select_language" msgid="3693815588777926848">"ภาษาสำหรับการป้อนข้อมูล"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"แตะอีกครั้งเพื่อบัน​​ทึก"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"มีพจนานุกรมให้ใช้งาน"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index a575d2f..edbe88a 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Walang naka-enable na pamamaraan ng pag-input ng boses. Suriin ang mga setting ng Pag-input ng wika."</string>
     <string name="configure_input_method" msgid="373356270290742459">"I-configure ang mga pamamaraan ng pag-input"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Mag-input ng mga wika"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Magpadala ng feedback"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Mga wika ng input"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pinduting muli upang i-save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Available ang diksyunaryo"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 22ed85c..87bafcc 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Hiçbir ses girişi yöntemi etkinleştirilmedi. Dil ve giriş ayarlarını kontrol edin."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Giriş yöntemlerini yapılandır"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Giriş dilleri"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Geri bildirim gönder"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Giriş dilleri"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Kaydetmek için tekrar dokunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sözlük kullanılabilir"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index f5802cd..63eb40b 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Способи голосового вводу не ввімкнено. Перейдіть у налаштування \"Мова та введення\"."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Налаштування методів введення"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Мови вводу"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Надіслати відгук"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Мови введення"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Торкніться знову, щоб зберегти"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Словник доступний"</string>
diff --git a/java/res/values-ur-rPK/strings.xml b/java/res/values-ur-rPK/strings.xml
index d1a92a2..fee6f15 100644
--- a/java/res/values-ur-rPK/strings.xml
+++ b/java/res/values-ur-rPK/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"کوئی صوتی اندراج کے طریقے فعال نہیں ہیں۔ زبان اور ان پٹ ترتیبات کو چیک کریں۔"</string>
     <string name="configure_input_method" msgid="373356270290742459">"اندراج کے طریقے کنفیگر کریں"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ان پٹ زبانیں"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"تاثرات بھیجیں"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"ان پٹ زبانیں"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"محفوظ کرنے کیلئے دوبارہ ٹچ کریں"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"لغت دستیاب ہے"</string>
diff --git a/java/res/values-uz-rUZ/strings.xml b/java/res/values-uz-rUZ/strings.xml
index 3610a47..adb7ad8 100644
--- a/java/res/values-uz-rUZ/strings.xml
+++ b/java/res/values-uz-rUZ/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ovoz bilan yozish usuli yoqilmagan. Til va matn kiritish sozlamalarini tekshiring."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Matn kiritish usullarini sozlash"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Matn kiritish tillari"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Fikr va mulohaza yuborish"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Matn kiritish tillari"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Saqlash uchun yana bosing"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Lug‘at mavjud"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index ae5de84..3965e4f 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Không có phương thức nhập bằng giọng nói nào được bật. Kiểm tra cài đặt Ngôn ngữ và phương thức nhập."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Định cấu hình phương thức nhập"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Ngôn ngữ nhập"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Gửi phản hồi"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"Ngôn ngữ nhập"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Chạm lại để lưu"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Có sẵn từ điển"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 4e21798..aec0c0c 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"未启用任何语音输入法。请检查“语言和输入法”设置。"</string>
     <string name="configure_input_method" msgid="373356270290742459">"配置输入法"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"输入语言"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"发送反馈"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"输入语言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次触摸即可保存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"有可用字典"</string>
diff --git a/java/res/values-zh-rHK/strings.xml b/java/res/values-zh-rHK/strings.xml
index df6ffc3..f74fa31 100644
--- a/java/res/values-zh-rHK/strings.xml
+++ b/java/res/values-zh-rHK/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"尚未啟用語音輸入法,請檢查語言和輸入設定。"</string>
     <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"傳送意見"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"輸入語言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次輕觸即可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 36e69b2..e371de2 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -77,7 +77,8 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"尚未啟動語音輸入法,請檢查語言與輸入設定。"</string>
     <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"提供意見"</string>
+    <!-- no translation found for help_and_feedback (5328219371839879161) -->
+    <skip />
     <string name="select_language" msgid="3693815588777926848">"輸入語言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次輕觸即可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可用的字典"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 97db060..689d501 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -77,7 +77,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Azikho izindlela zokufaka zezwi ezinikwe amandla. Hlola izilungiselelo zolimi kanye nezokufaka."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Misa izindlela zokufakwayo"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Izilimi zokufakwayo"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Thumela impendulo"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Usizo nempendulo"</string>
     <string name="select_language" msgid="3693815588777926848">"Izilimi zokufakwayo"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Thinta futhi ukuze ulondoloze"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Isichazamazwi siyatholakala"</string>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index bfe3856..e89912a 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -242,7 +242,8 @@
         <attr name="iconZwnjKey" format="reference" />
         <attr name="iconZwjKey" format="reference" />
         <attr name="iconImeKey" format="reference" />
-        <attr name="iconEmojiKey" format="reference" />
+        <attr name="iconEmojiActionKey" format="reference" />
+        <attr name="iconEmojiNormalKey" format="reference" />
     </declare-styleable>
 
     <declare-styleable name="Keyboard_GridRows">
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index e3f0aea..b25a208 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -22,10 +22,12 @@
          See {@link SettingsValues#needsToShowVoiceInputKey(SharedPreferences,Resources)} -->
     <string name="voice_mode_main">0</string>
 
-    <!-- Title for Latin keyboard debug settings activity / dialog -->
-    <string name="english_ime_debug_settings">Android keyboard Debug settings</string>
+    <!-- Title for Android keyboard debug settings activity / dialog -->
+    <string name="english_ime_debug_settings">Android Keyboard Debug settings</string>
     <string name="prefs_debug_mode">Debug Mode</string>
     <string name="prefs_force_non_distinct_multitouch">Force non-distinct multitouch</string>
+    <string name="prefs_force_physical_keyboard_special_key">Force physical keyboard special key</string>
+    <string name="prefs_show_ui_to_accept_typed_word">Show UI to accept typed word</string>
 
     <!-- Subtype locale display name exceptions.
          For each exception, there should be related string resources for display name that may have
diff --git a/java/res/values/keyboard-icons-holo.xml b/java/res/values/keyboard-icons-holo.xml
index d95ff82..f5484bf 100644
--- a/java/res/values/keyboard-icons-holo.xml
+++ b/java/res/values/keyboard-icons-holo.xml
@@ -35,6 +35,7 @@
         <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_dark</item>
         <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo_dark</item>
         <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo_dark</item>
-        <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_holo_dark</item>
+        <item name="iconEmojiActionKey">@drawable/sym_keyboard_smiley_holo_dark</item>
+        <item name="iconEmojiNormalKey">@drawable/sym_keyboard_smiley_holo_dark</item>
     </style>
 </resources>
diff --git a/java/res/values/keyboard-icons-lxx-dark.xml b/java/res/values/keyboard-icons-lxx-dark.xml
index dfa585c..305df02 100644
--- a/java/res/values/keyboard-icons-lxx-dark.xml
+++ b/java/res/values/keyboard-icons-lxx-dark.xml
@@ -40,6 +40,7 @@
         <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_lxx_dark</item>
         <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_lxx_dark</item>
         <item name="iconZwjKey">@drawable/sym_keyboard_zwj_lxx_dark</item>
-        <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
+        <item name="iconEmojiActionKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
+        <item name="iconEmojiNormalKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
     </style>
 </resources>
diff --git a/java/res/values/keyboard-icons-lxx-light.xml b/java/res/values/keyboard-icons-lxx-light.xml
index e8a3c56..866dc68 100644
--- a/java/res/values/keyboard-icons-lxx-light.xml
+++ b/java/res/values/keyboard-icons-lxx-light.xml
@@ -40,6 +40,9 @@
         <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_lxx_light</item>
         <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_lxx_light</item>
         <item name="iconZwjKey">@drawable/sym_keyboard_zwj_lxx_light</item>
-        <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_lxx_light</item>
+        <!-- Use white emoji icon (for lxx_dark) because an action key has green/dark color background. -->
+        <item name="iconEmojiActionKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
+        <!-- Use dark green emoji icon (for lxx_light) because a normal key has white color background. -->
+        <item name="iconEmojiNormalKey">@drawable/sym_keyboard_smiley_lxx_light</item>
     </style>
 </resources>
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index 877c796..1b52b1e 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -105,7 +105,7 @@
         latin:altCode="!code/key_space" />
     <key-style
         latin:styleName="emojiKeyStyle"
-        latin:keySpec="!icon/emoji_key|!code/key_emoji"
+        latin:keySpec="!icon/emoji_normal_key|!code/key_emoji"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
diff --git a/java/res/xml-sw600dp/key_styles_enter.xml b/java/res/xml-sw600dp/key_styles_enter.xml
index d0167d3..c20523b 100644
--- a/java/res/xml-sw600dp/key_styles_enter.xml
+++ b/java/res/xml-sw600dp/key_styles_enter.xml
@@ -21,7 +21,6 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <!-- TODO: Stop using many conditional cases for keyspec_emoji_key. There are way too many to maintain. -->
     <!-- Navigate more keys style -->
     <switch>
         <!-- latin:passwordInput="true" -->
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index bc739f7..2d006c9 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -80,7 +80,7 @@
     <!-- emojiKeyStyle must be defined before including @xml/key_syles_enter. -->
     <key-style
         latin:styleName="emojiKeyStyle"
-        latin:keySpec="!icon/emoji_key|!code/key_emoji"
+        latin:keySpec="!icon/emoji_action_key|!code/key_emoji"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="action" />
     <include
diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml
index 960c79c..55dab78 100644
--- a/java/res/xml/key_styles_enter.xml
+++ b/java/res/xml/key_styles_enter.xml
@@ -21,7 +21,7 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <!-- TODO: Stop using many conditional cases for keyspec_emoji_key. There are way too many to maintain. -->
+    <!-- TODO: Stop using many conditional cases for keyspec_emoji_action_key. There are way too many to maintain. -->
     <!-- Navigate more keys style -->
     <switch>
         <!-- latin:passwordInput="true" -->
@@ -182,7 +182,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_previous" />
+                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_previous" />
         </case>
         <case
             latin:imeAction="actionNext"
@@ -191,7 +191,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!text/keyspec_emoji_key" />
+                latin:moreKeys="!text/keyspec_emoji_action_key" />
         </case>
         <case
             latin:imeAction="actionPrevious"
@@ -200,7 +200,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_next" />
+                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_next" />
         </case>
         <case
             latin:imeAction="actionPrevious"
@@ -209,7 +209,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!text/keyspec_emoji_key" />
+                latin:moreKeys="!text/keyspec_emoji_action_key" />
         </case>
         <case
             latin:navigateNext="true"
@@ -218,7 +218,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!fixedColumnOrder!3,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_previous,!text/keyspec_action_next" />
+                latin:moreKeys="!fixedColumnOrder!3,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_previous,!text/keyspec_action_next" />
         </case>
         <case
             latin:navigateNext="true"
@@ -227,7 +227,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_next" />
+                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_next" />
         </case>
         <case
             latin:navigateNext="false"
@@ -236,7 +236,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_previous" />
+                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_previous" />
         </case>
         <case
             latin:navigateNext="false"
@@ -245,7 +245,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!text/keyspec_emoji_key" />
+                latin:moreKeys="!text/keyspec_emoji_action_key" />
         </case>
         <default>
             <key-style
diff --git a/java/res/xml/prefs_screen_debug.xml b/java/res/xml/prefs_screen_debug.xml
index ae29a8a..965369a 100644
--- a/java/res/xml/prefs_screen_debug.xml
+++ b/java/res/xml/prefs_screen_debug.xml
@@ -31,6 +31,16 @@
         android:defaultValue="false"
         android:persistent="true" />
     <CheckBoxPreference
+        android:key="force_physical_keyboard_special_key"
+        android:title="@string/prefs_force_physical_keyboard_special_key"
+        android:defaultValue="false"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_show_ui_to_accept_typed_word"
+        android:title="@string/prefs_show_ui_to_accept_typed_word"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
         android:key="pref_sliding_key_input_preview"
         android:title="@string/sliding_key_input_preview"
         android:summary="@string/sliding_key_input_preview_summary"
diff --git a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java
new file mode 100644
index 0000000..7d1717b
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.os.Build;
+
+public final class BuildCompatUtils {
+    private BuildCompatUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    private static final boolean IS_RELEASE_BUILD = Build.VERSION.CODENAME.equals("REL");
+
+    /**
+     * The "effective" API version.
+     * {@link android.os.Build.VERSION#SDK_INT} if the platform is a release build.
+     * {@link android.os.Build.VERSION#SDK_INT} plus 1 if the platform is a development build.
+     */
+    public static final int EFFECTIVE_SDK_INT = IS_RELEASE_BUILD
+            ? Build.VERSION.SDK_INT
+            : Build.VERSION.SDK_INT + 1;
+
+    /**
+     * API version for L-release.
+     */
+    // TODO: Substitute this constant reference with Build.VERSION_CODES.L* once the *next* version
+    // becomes available.
+    public static final int VERSION_CODES_LXX = 21;
+}
diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
new file mode 100644
index 0000000..2cec142
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.lang.reflect.Method;
+
+@UsedForTesting
+public final class CursorAnchorInfoCompatWrapper {
+    // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX).
+    private static Class<?> getCursorAnchorInfoClass() {
+        try {
+            return Class.forName("android.view.inputmethod.CursorAnchorInfo");
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+    private static final Class<?> CLASS;
+    private static final Method METHOD_GET_CHARACTER_RECT;
+    private static final Method METHOD_GET_CHARACTER_RECT_FLAGS;
+    private static final Method METHOD_GET_COMPOSING_TEXT;
+    private static final Method METHOD_GET_COMPOSING_TEXT_START;
+    private static final Method METHOD_GET_MATRIX;
+    static {
+        CLASS = getCursorAnchorInfoClass();
+        METHOD_GET_CHARACTER_RECT = CompatUtils.getMethod(CLASS, "getCharacterRect", int.class);
+        METHOD_GET_CHARACTER_RECT_FLAGS = CompatUtils.getMethod(CLASS, "getCharacterRectFlags",
+                int.class);
+        METHOD_GET_COMPOSING_TEXT = CompatUtils.getMethod(CLASS, "getComposingText");
+        METHOD_GET_COMPOSING_TEXT_START = CompatUtils.getMethod(CLASS, "getComposingTextStart");
+        METHOD_GET_MATRIX = CompatUtils.getMethod(CLASS, "getMatrix");
+    }
+
+    @UsedForTesting
+    public static boolean isAvailable() {
+        return CLASS != null;
+    }
+
+    public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
+
+    /**
+     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this
+     * character. Editor authors should not use this flag.
+     */
+    public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0;
+
+    /**
+     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible.
+     */
+    public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1;
+
+    /**
+     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible.
+     */
+    public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2;
+
+    /**
+     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible.
+     */
+    public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3;
+
+    /**
+     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle
+     * for this character. Input method authors should ignore the returned rectangle.
+     */
+    public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4;
+
+    private Object mInstance;
+
+    private CursorAnchorInfoCompatWrapper(final Object instance) {
+        mInstance = instance;
+    }
+
+    @UsedForTesting
+    public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) {
+        if (!isAvailable()) {
+            return new CursorAnchorInfoCompatWrapper(null);
+        }
+        return new CursorAnchorInfoCompatWrapper(instance);
+    }
+
+    private static final class FakeHolder {
+        static CursorAnchorInfoCompatWrapper sInstance = new CursorAnchorInfoCompatWrapper(null);
+    }
+
+    @UsedForTesting
+    public static CursorAnchorInfoCompatWrapper getFake() {
+        return FakeHolder.sInstance;
+    }
+
+    public CharSequence getComposingText() {
+        return (CharSequence) CompatUtils.invoke(mInstance, null, METHOD_GET_COMPOSING_TEXT);
+    }
+
+    private static int COMPOSING_TEXT_START_DEFAULT = -1;
+    public int getComposingTextStart() {
+        if (mInstance == null || METHOD_GET_COMPOSING_TEXT_START == null) {
+            return COMPOSING_TEXT_START_DEFAULT;
+        }
+        return (int) CompatUtils.invoke(mInstance, null, METHOD_GET_COMPOSING_TEXT_START);
+    }
+
+    public Matrix getMatrix() {
+        return (Matrix) CompatUtils.invoke(mInstance, null, METHOD_GET_MATRIX);
+    }
+
+    public RectF getCharacterRect(final int index) {
+        return (RectF) CompatUtils.invoke(mInstance, null, METHOD_GET_CHARACTER_RECT, index);
+    }
+
+    public int getCharacterRectFlags(final int index) {
+        if (mInstance == null || METHOD_GET_CHARACTER_RECT_FLAGS == null) {
+            return CHARACTER_RECT_TYPE_UNSPECIFIED;
+        }
+        return (int) CompatUtils.invoke(mInstance, null, METHOD_GET_CHARACTER_RECT_FLAGS, index);
+    }
+}
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index f02f788..ef5b047 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -257,6 +257,8 @@
 
     public boolean isConsumed() { return 0 != (FLAG_CONSUMED & mFlags); }
 
+    public boolean isGesture() { return EVENT_TYPE_GESTURE == mEventType; }
+
     // Returns whether this is a fake key press from the suggestion strip. This happens with
     // punctuation signs selected from the suggestion strip.
     public boolean isSuggestionStripPress() {
diff --git a/java/src/com/android/inputmethod/event/InputTransaction.java b/java/src/com/android/inputmethod/event/InputTransaction.java
index b18bf56..5bc9111 100644
--- a/java/src/com/android/inputmethod/event/InputTransaction.java
+++ b/java/src/com/android/inputmethod/event/InputTransaction.java
@@ -33,7 +33,7 @@
 
     // Initial conditions
     public final SettingsValues mSettingsValues;
-    private final Event mEvent;
+    public final Event mEvent;
     public final long mTimestamp;
     public final int mSpaceState;
     public final int mShiftState;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index f351267..140e768 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.preference.PreferenceManager;
 import android.util.Log;
@@ -233,11 +234,21 @@
     }
 
     private void setMainKeyboardFrame() {
-        mMainKeyboardFrame.setVisibility(View.VISIBLE);
+        mMainKeyboardFrame.setVisibility(hasHardwareKeyboard() ? View.GONE : View.VISIBLE);
         mEmojiPalettesView.setVisibility(View.GONE);
         mEmojiPalettesView.stopEmojiPalettes();
     }
 
+    // TODO: Move this boolean to a member of {@link SettingsValues} and reset it
+    // at {@link LatinIME#onConfigurationChanged(Configuration)}.
+    public boolean hasHardwareKeyboard() {
+        // Copied from {@link InputMethodServce#onEvaluateInputViewShown()}.
+        final Configuration config = mLatinIME.getResources().getConfiguration();
+        final boolean noHardwareKeyboard = config.keyboard == Configuration.KEYBOARD_NOKEYS
+                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
+        return !noHardwareKeyboard;
+    }
+
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setEmojiKeyboard() {
@@ -249,6 +260,14 @@
         mEmojiPalettesView.setVisibility(View.VISIBLE);
     }
 
+    public void onToggleEmojiKeyboard() {
+        if (isShowingEmojiPalettes()) {
+            setAlphabetKeyboard();
+        } else {
+            setEmojiKeyboard();
+        }
+    }
+
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsShiftedKeyboard() {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
index 4c2e0dd..0cd606d 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
@@ -17,11 +17,11 @@
 package com.android.inputmethod.keyboard;
 
 import android.content.SharedPreferences;
-import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.util.Log;
 
 import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.compat.BuildCompatUtils;
 import com.android.inputmethod.latin.R;
 
 import java.util.Arrays;
@@ -47,8 +47,7 @@
                 VERSION_CODES.ICE_CREAM_SANDWICH),
         new KeyboardTheme(THEME_ID_LXX_LIGHT, R.style.KeyboardTheme_LXX_Light,
                 // Default theme for LXX.
-                // TODO: Update this constant once the *next* version becomes available.
-                VERSION_CODES.CUR_DEVELOPMENT),
+                BuildCompatUtils.VERSION_CODES_LXX),
         new KeyboardTheme(THEME_ID_LXX_DARK, R.style.KeyboardTheme_LXX_Dark,
                 VERSION_CODES.BASE),
     };
@@ -99,15 +98,6 @@
         return null;
     }
 
-    private static int getSdkVersion() {
-        final int sdkVersion = Build.VERSION.SDK_INT;
-        // TODO: Consider to remove this check once the *next* version becomes available.
-        if (sdkVersion > VERSION_CODES.KITKAT) {
-            return VERSION_CODES.CUR_DEVELOPMENT;
-        }
-        return sdkVersion;
-    }
-
     @UsedForTesting
     static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs,
             final int sdkVersion) {
@@ -140,7 +130,7 @@
 
     public static void saveKeyboardThemeId(final String themeIdString,
             final SharedPreferences prefs) {
-        saveKeyboardThemeId(themeIdString, prefs, getSdkVersion());
+        saveKeyboardThemeId(themeIdString, prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
     }
 
     @UsedForTesting
@@ -159,7 +149,7 @@
     }
 
     public static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs) {
-        return getKeyboardTheme(prefs, getSdkVersion());
+        return getKeyboardTheme(prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
     }
 
     @UsedForTesting
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 702efb3..1ef53a6 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -46,6 +46,7 @@
 import com.android.inputmethod.keyboard.internal.KeyDrawParams;
 import com.android.inputmethod.keyboard.internal.KeyPreviewChoreographer;
 import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
+import com.android.inputmethod.keyboard.internal.KeyPreviewView;
 import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
 import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
@@ -764,6 +765,9 @@
     public void startDisplayLanguageOnSpacebar(final boolean subtypeChanged,
             final int languageOnSpacebarFormatType,
             final boolean hasMultipleEnabledIMEsOrSubtypes) {
+        if (subtypeChanged) {
+            KeyPreviewView.clearTextCache();
+        }
         mLanguageOnSpacebarFormatType = languageOnSpacebarFormatType;
         mHasMultipleEnabledIMEsOrSubtypes = hasMultipleEnabledIMEsOrSubtypes;
         final ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator;
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
index 512d461..0f9dc85 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
@@ -24,6 +24,7 @@
 import android.util.Log;
 import android.util.Pair;
 
+import com.android.inputmethod.compat.BuildCompatUtils;
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
@@ -121,9 +122,7 @@
                     sCategoryTabIconAttr[i], 0);
         }
         addShownCategoryId(EmojiCategory.ID_RECENTS);
-        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
-                || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
-                || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
+        if (BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.KITKAT) {
             addShownCategoryId(EmojiCategory.ID_PEOPLE);
             addShownCategoryId(EmojiCategory.ID_OBJECTS);
             addShownCategoryId(EmojiCategory.ID_NATURE);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
index 360faf8..2453860 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
@@ -17,7 +17,10 @@
 package com.android.inputmethod.keyboard.internal;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.text.TextPaint;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.Gravity;
@@ -26,6 +29,8 @@
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.latin.R;
 
+import java.util.HashSet;
+
 /**
  * The pop up key preview view.
  */
@@ -34,6 +39,9 @@
     public static final int POSITION_LEFT = 1;
     public static final int POSITION_RIGHT = 2;
 
+    private final Rect mBackgroundPadding = new Rect();
+    private static final HashSet<String> sNoScaleXTextSet = new HashSet<>();
+
     public KeyPreviewView(final Context context, final AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -58,7 +66,48 @@
         setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams));
         setTypeface(key.selectPreviewTypeface(drawParams));
         // TODO Should take care of temporaryShiftLabel here.
-        setText(key.getPreviewLabel());
+        setTextAndScaleX(key.getPreviewLabel());
+    }
+
+    private void setTextAndScaleX(final String text) {
+        setTextScaleX(1.0f);
+        setText(text);
+        if (sNoScaleXTextSet.contains(text)) {
+            return;
+        }
+        // TODO: Override {@link #setBackground(Drawable)} that is supported from API 16 and
+        // calculate maximum text width.
+        final Drawable background = getBackground();
+        if (background == null) {
+            return;
+        }
+        background.getPadding(mBackgroundPadding);
+        final int maxWidth = background.getIntrinsicWidth() - mBackgroundPadding.left
+                - mBackgroundPadding.right;
+        final float width = getTextWidth(text, getPaint());
+        if (width <= maxWidth) {
+            sNoScaleXTextSet.add(text);
+            return;
+        }
+        setTextScaleX(maxWidth / width);
+    }
+
+    public static void clearTextCache() {
+        sNoScaleXTextSet.clear();
+    }
+
+    private static float getTextWidth(final String text, final TextPaint paint) {
+        if (TextUtils.isEmpty(text)) {
+            return 0.0f;
+        }
+        final int len = text.length();
+        final float[] widths = new float[len];
+        final int count = paint.getTextWidths(text, 0, len, widths);
+        float width = 0;
+        for (int i = 0; i < count; i++) {
+            width += widths[i];
+        }
+        return width;
     }
 
     // Background state set
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 09550c4..e1f302c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -53,7 +53,8 @@
     public static final String NAME_LANGUAGE_SWITCH_KEY = "language_switch_key";
     public static final String NAME_ZWNJ_KEY = "zwnj_key";
     public static final String NAME_ZWJ_KEY = "zwj_key";
-    public static final String NAME_EMOJI_KEY = "emoji_key";
+    public static final String NAME_EMOJI_ACTION_KEY = "emoji_action_key";
+    public static final String NAME_EMOJI_NORMAL_KEY = "emoji_normal_key";
 
     private static final SparseIntArray ATTR_ID_TO_ICON_ID = new SparseIntArray();
 
@@ -81,7 +82,8 @@
         NAME_LANGUAGE_SWITCH_KEY,         R.styleable.Keyboard_iconLanguageSwitchKey,
         NAME_ZWNJ_KEY,                    R.styleable.Keyboard_iconZwnjKey,
         NAME_ZWJ_KEY,                     R.styleable.Keyboard_iconZwjKey,
-        NAME_EMOJI_KEY,                   R.styleable.Keyboard_iconEmojiKey,
+        NAME_EMOJI_ACTION_KEY,            R.styleable.Keyboard_iconEmojiActionKey,
+        NAME_EMOJI_NORMAL_KEY,            R.styleable.Keyboard_iconEmojiNormalKey,
     };
 
     private static int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index e6897bf..31bc549 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -250,7 +250,7 @@
         /* 164: 0 */ "morekeys_single_quote",
         /* 165: 0 */ "morekeys_double_quote",
         /* 166: 0 */ "morekeys_tablet_double_quote",
-        /* 167: 0 */ "keyspec_emoji_key",
+        /* 167: 0 */ "keyspec_emoji_action_key",
     };
 
     private static final String EMPTY = "";
@@ -464,7 +464,7 @@
         /* morekeys_single_quote */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes",
         /* morekeys_double_quote */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes",
         /* morekeys_tablet_double_quote */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes",
-        /* keyspec_emoji_key */ "!icon/emoji_key|!code/key_emoji",
+        /* keyspec_emoji_action_key */ "!icon/emoji_action_key|!code/key_emoji",
     };
 
     /* Locale af: Afrikaans */
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c11a220..22b9170 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -647,7 +647,7 @@
     @UsedForTesting
     public void waitAllTasksForTests() {
         final CountDownLatch countDownLatch = new CountDownLatch(1);
-        ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
+        asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
                 countDownLatch.countDown();
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 2e3cd6b..71fd10e 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -49,11 +49,13 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
 import com.android.inputmethod.compat.InputConnectionCompatUtils;
 import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
 import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
@@ -136,7 +138,7 @@
                     new Runnable() {
                         @Override
                         public void run() {
-                            mHandler.postUpdateSuggestionStrip();
+                            mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
                         }
                     });
     private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
@@ -145,6 +147,8 @@
     // If it turns out we need several, it will get grown seamlessly.
     final SparseArray<HardwareEventDecoder> mHardwareEventDecoders = new SparseArray<>(1);
 
+    // TODO: Move these {@link View}s to {@link KeyboardSwitcher}.
+    private View mInputView;
     private View mExtractArea;
     private View mKeyPreviewBackingView;
     private SuggestionStripView mSuggestionStripView;
@@ -153,6 +157,7 @@
     @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
     private final SubtypeSwitcher mSubtypeSwitcher;
     private final SubtypeState mSubtypeState = new SubtypeState();
+    private final SpecialKeyDetector mSpecialKeyDetector;
 
     // Object for reacting to adding/removing a dictionary pack.
     private final BroadcastReceiver mDictionaryPackInstallReceiver =
@@ -215,7 +220,7 @@
             case MSG_UPDATE_SUGGESTION_STRIP:
                 cancelUpdateSuggestionStrip();
                 latinIme.mInputLogic.performUpdateSuggestionStripSync(
-                        latinIme.mSettings.getCurrent());
+                        latinIme.mSettings.getCurrent(), msg.arg1 /* inputStyle */);
                 break;
             case MSG_UPDATE_SHIFT_STATE:
                 switcher.requestUpdatingShiftState(latinIme.getCurrentAutoCapsState(),
@@ -265,8 +270,9 @@
             }
         }
 
-        public void postUpdateSuggestionStrip() {
-            sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION_STRIP), mDelayUpdateSuggestions);
+        public void postUpdateSuggestionStrip(final int inputStyle) {
+            sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION_STRIP, inputStyle,
+                    0 /* ignored */), mDelayUpdateSuggestions);
         }
 
         public void postReopenDictionaries() {
@@ -419,9 +425,12 @@
                                 latinIme.getCurrentInputConnection(), true /* enableMonitor */);
                     }
                     if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
-                        InputConnectionCompatUtils.requestCursorAnchorInfo(
-                                latinIme.getCurrentInputConnection(), true /* enableMonitor */,
-                                true /* requestImmediateCallback */);
+                        // AcceptTypedWord feature relies on CursorAnchorInfo.
+                        if (latinIme.mSettings.getCurrent().mShouldShowUiToAcceptTypedWord) {
+                            InputConnectionCompatUtils.requestCursorAnchorInfo(
+                                    latinIme.getCurrentInputConnection(), true /* enableMonitor */,
+                                    true /* requestImmediateCallback */);
+                        }
                     }
                 }
             }
@@ -514,6 +523,7 @@
         mSettings = Settings.getInstance();
         mSubtypeSwitcher = SubtypeSwitcher.getInstance();
         mKeyboardSwitcher = KeyboardSwitcher.getInstance();
+        mSpecialKeyDetector = new SpecialKeyDetector(this);
         mIsHardwareAcceleratedDrawingEnabled =
                 InputMethodServiceCompatUtils.enableHardwareAcceleration(this);
         Log.i(TAG, "Hardware accelerated drawing: " + mIsHardwareAcceleratedDrawingEnabled);
@@ -709,6 +719,7 @@
     @Override
     public void setInputView(final View view) {
         super.setInputView(view);
+        mInputView = view;
         mExtractArea = getWindow().getWindow().getDecorView()
                 .findViewById(android.R.id.extractArea);
         mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing);
@@ -967,6 +978,16 @@
         super.onUpdateCursor(rect);
     }
 
+    // We cannot mark this method as @Override until new SDK becomes publicly available.
+    // @Override
+    public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) {
+        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
+            final CursorAnchorInfoCompatWrapper wrapper =
+                    CursorAnchorInfoCompatWrapper.fromObject(info);
+            // TODO: Implement here
+        }
+    }
+
     /**
      * This is called when the user has clicked on the extracted text view,
      * when running in fullscreen mode.  The default implementation hides
@@ -1040,7 +1061,8 @@
                         applicationSpecifiedCompletions);
         final SuggestedWords suggestedWords = new SuggestedWords(applicationSuggestedWords,
                 null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */,
-                false /* isObsoleteSuggestions */, false /* isPrediction */);
+                false /* isObsoleteSuggestions */, false /* isPrediction */,
+                SuggestedWords.INPUT_STYLE_APPLICATION_SPECIFIED /* inputStyle */);
         // When in fullscreen mode, show completions generated by the application forcibly
         setSuggestedWords(suggestedWords);
     }
@@ -1079,6 +1101,14 @@
         if (visibleKeyboardView == null || !hasSuggestionStripView()) {
             return;
         }
+        final boolean hasHardwareKeyboard = mKeyboardSwitcher.hasHardwareKeyboard();
+        if (hasHardwareKeyboard && visibleKeyboardView.getVisibility() == View.GONE) {
+            // If there is a hardware keyboard and a visible software keyboard view has been hidden,
+            // no visual element will be shown on the screen.
+            outInsets.touchableInsets = mInputView.getHeight();
+            outInsets.visibleTopInsets = mInputView.getHeight();
+            return;
+        }
         final int adjustedBackingHeight = getAdjustedBackingViewHeight();
         final boolean backingGone = (mKeyPreviewBackingView.getVisibility() == View.GONE);
         final int backingHeight = backingGone ? 0 : adjustedBackingHeight;
@@ -1111,7 +1141,17 @@
     }
 
     @Override
+    public boolean onEvaluateInputViewShown() {
+        // Always show {@link InputView}.
+        return true;
+    }
+
+    @Override
     public boolean onEvaluateFullscreenMode() {
+        if (mKeyboardSwitcher.hasHardwareKeyboard()) {
+            // If there is a hardware keyboard, disable full screen mode.
+            return false;
+        }
         // Reread resource value here, because this method is called by the framework as needed.
         final boolean isFullscreenModeAllowed = Settings.readUseFullscreenMode(getResources());
         if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) {
@@ -1413,7 +1453,7 @@
     }
 
     // TODO[IL]: Move this out of LatinIME.
-    public void getSuggestedWords(final int sessionId, final int sequenceNumber,
+    public void getSuggestedWords(final int inputStyle, final int sequenceNumber,
             final OnGetSuggestedWordsCallback callback) {
         final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
         if (keyboard == null) {
@@ -1421,7 +1461,7 @@
             return;
         }
         mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(),
-                mKeyboardSwitcher.getKeyboardShiftMode(), sessionId, sequenceNumber, callback);
+                mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback);
     }
 
     @Override
@@ -1505,7 +1545,16 @@
         default: // SHIFT_NO_UPDATE
         }
         if (inputTransaction.requiresUpdateSuggestions()) {
-            mHandler.postUpdateSuggestionStrip();
+            final int inputStyle;
+            if (inputTransaction.mEvent.isSuggestionStripPress()) {
+                // Suggestion strip press: no input.
+                inputStyle = SuggestedWords.INPUT_STYLE_NONE;
+            } else if (inputTransaction.mEvent.isGesture()) {
+                inputStyle = SuggestedWords.INPUT_STYLE_TAIL_BATCH;
+            } else {
+                inputStyle = SuggestedWords.INPUT_STYLE_TYPING;
+            }
+            mHandler.postUpdateSuggestionStrip(inputStyle);
         }
         if (inputTransaction.didAffectContents()) {
             mSubtypeState.setCurrentSubtypeHasBeenUsed();
@@ -1568,6 +1617,7 @@
     // Hooks for hardware keyboard
     @Override
     public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
+        mSpecialKeyDetector.onKeyDown(keyEvent);
         if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
             return super.onKeyDown(keyCode, keyEvent);
         }
@@ -1587,12 +1637,16 @@
     }
 
     @Override
-    public boolean onKeyUp(final int keyCode, final KeyEvent event) {
-        final long keyIdentifier = event.getDeviceId() << 32 + event.getKeyCode();
+    public boolean onKeyUp(final int keyCode, final KeyEvent keyEvent) {
+        mSpecialKeyDetector.onKeyUp(keyEvent);
+        if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
+            return super.onKeyUp(keyCode, keyEvent);
+        }
+        final long keyIdentifier = keyEvent.getDeviceId() << 32 + keyEvent.getKeyCode();
         if (mInputLogic.mCurrentlyPressedHardwareKeys.remove(keyIdentifier)) {
             return true;
         }
-        return super.onKeyUp(keyCode, event);
+        return super.onKeyUp(keyCode, keyEvent);
     }
 
     // onKeyDown and onKeyUp are the main events we are interested in. There are two more events
diff --git a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
index 0fba37c..6b0205c 100644
--- a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
@@ -35,7 +35,8 @@
                 false /* typedWordValid */,
                 false /* hasAutoCorrectionCandidate */,
                 false /* isObsoleteSuggestions */,
-                false /* isPrediction */);
+                false /* isPrediction */,
+                INPUT_STYLE_NONE /* inputStyle */);
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java b/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java
new file mode 100644
index 0000000..27b2f50
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java
@@ -0,0 +1,43 @@
+/*
+ * 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.latin;
+
+import android.content.Context;
+import android.view.KeyEvent;
+
+final class SpecialKeyDetector {
+    /**
+     * Special physical key detector
+     * @param context a context of this detector.
+     */
+    public SpecialKeyDetector(final Context context) {
+    }
+
+    /**
+     * Record a down key event.
+     * @param keyEvent a down key event.
+     */
+    public void onKeyDown(final KeyEvent keyEvent) {
+    }
+
+    /**
+     * Record an up key event.
+     * @param keyEvent an up key event.
+     */
+    public void onKeyUp(final KeyEvent keyEvent) {
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index b8b6d64..ab852f8 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -40,13 +40,8 @@
     // Session id for
     // {@link #getSuggestedWords(WordComposer,String,ProximityInfo,boolean,int)}.
     // We are sharing the same ID between typing and gesture to save RAM footprint.
-    public static final int SESSION_TYPING = 0;
-    public static final int SESSION_GESTURE = 0;
-
-    // TODO: rename this to CORRECTION_OFF
-    public static final int CORRECTION_NONE = 0;
-    // TODO: rename this to CORRECTION_ON
-    public static final int CORRECTION_FULL = 1;
+    public static final int SESSION_ID_TYPING = 0;
+    public static final int SESSION_ID_GESTURE = 0;
 
     // Close to -2**31
     private static final int SUPPRESS_SUGGEST_THRESHOLD = -2000000000;
@@ -75,14 +70,15 @@
     public void getSuggestedWords(final WordComposer wordComposer,
             final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
-            final boolean isCorrectionEnabled, final int sessionId, final int sequenceNumber,
+            final boolean isCorrectionEnabled, final int inputStyle, final int sequenceNumber,
             final OnGetSuggestedWordsCallback callback) {
         if (wordComposer.isBatchMode()) {
             getSuggestedWordsForBatchInput(wordComposer, prevWordsInfo, proximityInfo,
-                    settingsValuesForSuggestion, sessionId, sequenceNumber, callback);
+                    settingsValuesForSuggestion, inputStyle, sequenceNumber, callback);
         } else {
-            getSuggestedWordsForTypingInput(wordComposer, prevWordsInfo, proximityInfo,
-                    settingsValuesForSuggestion, isCorrectionEnabled, sequenceNumber, callback);
+            getSuggestedWordsForNonBatchInput(wordComposer, prevWordsInfo, proximityInfo,
+                    settingsValuesForSuggestion, inputStyle, isCorrectionEnabled,
+                    sequenceNumber, callback);
         }
     }
 
@@ -120,11 +116,11 @@
         return firstSuggestedWordInfo.mWord;
     }
 
-    // Retrieves suggestions for the typing input
+    // Retrieves suggestions for non-batch input (typing, recorrection, predictions...)
     // and calls the callback function with the suggestions.
-    private void getSuggestedWordsForTypingInput(final WordComposer wordComposer,
+    private void getSuggestedWordsForNonBatchInput(final WordComposer wordComposer,
             final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
-            final SettingsValuesForSuggestion settingsValuesForSuggestion,
+            final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyle,
             final boolean isCorrectionEnabled, final int sequenceNumber,
             final OnGetSuggestedWordsCallback callback) {
         final String typedWord = wordComposer.getTypedWord();
@@ -135,7 +131,7 @@
 
         final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
                 wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion,
-                SESSION_TYPING);
+                SESSION_ID_TYPING);
         final ArrayList<SuggestedWordInfo> suggestionsContainer =
                 getTransformedSuggestedWordInfoList(wordComposer, suggestionResults,
                         trailingSingleQuotesCount);
@@ -197,7 +193,8 @@
                 // rename the attribute or change the value.
                 !resultsArePredictions && !allowsToBeAutoCorrected /* typedWordValid */,
                 hasAutoCorrection /* willAutoCorrect */,
-                false /* isObsoleteSuggestions */, resultsArePredictions, sequenceNumber));
+                false /* isObsoleteSuggestions */, resultsArePredictions,
+                inputStyle, sequenceNumber));
     }
 
     // Retrieves suggestions for the batch input
@@ -205,10 +202,11 @@
     private void getSuggestedWordsForBatchInput(final WordComposer wordComposer,
             final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
-            final int sessionId, final int sequenceNumber,
+            final int inputStyle, final int sequenceNumber,
             final OnGetSuggestedWordsCallback callback) {
         final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
-                wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion, sessionId);
+                wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion,
+                SESSION_ID_GESTURE);
         final ArrayList<SuggestedWordInfo> suggestionsContainer =
                 new ArrayList<>(suggestionResults);
         final int suggestionsCount = suggestionsContainer.size();
@@ -246,7 +244,8 @@
                 true /* typedWordValid */,
                 false /* willAutoCorrect */,
                 false /* isObsoleteSuggestions */,
-                false /* isPrediction */, sequenceNumber));
+                false /* isPrediction */,
+                inputStyle, sequenceNumber));
     }
 
     private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 5231cc8..d7693af 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -31,12 +31,20 @@
     public static final int INDEX_OF_AUTO_CORRECTION = 1;
     public static final int NOT_A_SEQUENCE_NUMBER = -1;
 
+    public static final int INPUT_STYLE_NONE = 0;
+    public static final int INPUT_STYLE_TYPING = 1;
+    public static final int INPUT_STYLE_UPDATE_BATCH = 2;
+    public static final int INPUT_STYLE_TAIL_BATCH = 3;
+    public static final int INPUT_STYLE_APPLICATION_SPECIFIED = 4;
+    public static final int INPUT_STYLE_RECORRECTION = 5;
+
     // The maximum number of suggestions available.
     public static final int MAX_SUGGESTIONS = 18;
 
     private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST = new ArrayList<>(0);
     public static final SuggestedWords EMPTY = new SuggestedWords(
-            EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false, false, false, false);
+            EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false, false, false, false,
+            INPUT_STYLE_NONE);
 
     public final String mTypedWord;
     public final boolean mTypedWordValid;
@@ -46,6 +54,9 @@
     public final boolean mWillAutoCorrect;
     public final boolean mIsObsoleteSuggestions;
     public final boolean mIsPrediction;
+    // How the input for these suggested words was done by the user. Must be one of the
+    // INPUT_STYLE_* constants above.
+    public final int mInputStyle;
     public final int mSequenceNumber; // Sequence number for auto-commit.
     protected final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList;
     public final ArrayList<SuggestedWordInfo> mRawSuggestions;
@@ -55,9 +66,10 @@
             final boolean typedWordValid,
             final boolean willAutoCorrect,
             final boolean isObsoleteSuggestions,
-            final boolean isPrediction) {
+            final boolean isPrediction,
+            final int inputStyle) {
         this(suggestedWordInfoList, rawSuggestions, typedWordValid, willAutoCorrect,
-                isObsoleteSuggestions, isPrediction, NOT_A_SEQUENCE_NUMBER);
+                isObsoleteSuggestions, isPrediction, inputStyle, NOT_A_SEQUENCE_NUMBER);
     }
 
     public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
@@ -66,11 +78,12 @@
             final boolean willAutoCorrect,
             final boolean isObsoleteSuggestions,
             final boolean isPrediction,
+            final int inputStyle,
             final int sequenceNumber) {
         this(suggestedWordInfoList, rawSuggestions,
                 (suggestedWordInfoList.isEmpty() || isPrediction) ? null
                         : suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord,
-                typedWordValid, willAutoCorrect, isObsoleteSuggestions, isPrediction,
+                typedWordValid, willAutoCorrect, isObsoleteSuggestions, isPrediction, inputStyle,
                 sequenceNumber);
     }
 
@@ -81,6 +94,7 @@
             final boolean willAutoCorrect,
             final boolean isObsoleteSuggestions,
             final boolean isPrediction,
+            final int inputStyle,
             final int sequenceNumber) {
         mSuggestedWordInfoList = suggestedWordInfoList;
         mRawSuggestions = rawSuggestions;
@@ -88,6 +102,7 @@
         mWillAutoCorrect = willAutoCorrect;
         mIsObsoleteSuggestions = isObsoleteSuggestions;
         mIsPrediction = isPrediction;
+        mInputStyle = inputStyle;
         mSequenceNumber = sequenceNumber;
         mTypedWord = typedWord;
     }
@@ -367,7 +382,7 @@
 
     // SuggestedWords is an immutable object, as much as possible. We must not just remove
     // words from the member ArrayList as some other parties may expect the object to never change.
-    public SuggestedWords getSuggestedWordsExcludingTypedWord() {
+    public SuggestedWords getSuggestedWordsExcludingTypedWord(final int inputStyle) {
         final ArrayList<SuggestedWordInfo> newSuggestions = new ArrayList<>();
         String typedWord = null;
         for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
@@ -383,7 +398,7 @@
         // no auto-correction should take place hence willAutoCorrect = false.
         return new SuggestedWords(newSuggestions, null /* rawSuggestions */, typedWord,
                 true /* typedWordValid */, false /* willAutoCorrect */, mIsObsoleteSuggestions,
-                mIsPrediction, NOT_A_SEQUENCE_NUMBER);
+                mIsPrediction, inputStyle, NOT_A_SEQUENCE_NUMBER);
     }
 
     // Creates a new SuggestedWordInfo from the currently suggested words that removes all but the
@@ -402,6 +417,7 @@
                     SuggestedWordInfo.NOT_A_CONFIDENCE));
         }
         return new SuggestedWords(newSuggestions, null /* rawSuggestions */, mTypedWordValid,
-                mWillAutoCorrect, mIsObsoleteSuggestions, mIsPrediction);
+                mWillAutoCorrect, mIsObsoleteSuggestions, mIsPrediction,
+                INPUT_STYLE_TAIL_BATCH);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlags.java b/java/src/com/android/inputmethod/latin/define/ProductionFlags.java
index d385cf8..461c226 100644
--- a/java/src/com/android/inputmethod/latin/define/ProductionFlags.java
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlags.java
@@ -29,7 +29,7 @@
      *  and prior. In general, this callback provides more detailed positional information,
      *  even though an explicit support is required by the editor.
      */
-    public static final boolean ENABLE_CURSOR_ANCHOR_INFO_CALLBACK = false;
+    public static final boolean ENABLE_CURSOR_ANCHOR_INFO_CALLBACK = true;
 
     /**
      * When true, enable {@link InputMethodService#onUpdateCursor} callback via
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 418866a..348bae6 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -216,7 +216,7 @@
         } else {
             resetComposingState(true /* alsoResetLastComposedWord */);
         }
-        handler.postUpdateSuggestionStrip();
+        handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_TYPING);
         final String text = performSpecificTldProcessingOnTextInput(rawText);
         if (SpaceState.PHANTOM == mSpaceState) {
             promotePhantomSpace(settingsValues);
@@ -288,9 +288,6 @@
             return inputTransaction;
         }
 
-        // We need to log before we commit, because the word composer will store away the user
-        // typed word.
-        final String replacedWord = mWordComposer.getTypedWord();
         commitChosenWord(settingsValues, suggestion,
                 LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR);
         mConnection.endBatchEdit();
@@ -311,7 +308,8 @@
             mSuggestionStripViewAccessor.showAddToDictionaryHint(suggestion);
         } else {
             // If we're not showing the "Touch again to save", then update the suggestion strip.
-            handler.postUpdateSuggestionStrip();
+            // That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
+            handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
         }
         return inputTransaction;
     }
@@ -1299,7 +1297,8 @@
                 prevWordsInfo, timeStampInSeconds, settingsValues.mBlockPotentiallyOffensive);
     }
 
-    public void performUpdateSuggestionStripSync(final SettingsValues settingsValues) {
+    public void performUpdateSuggestionStripSync(final SettingsValues settingsValues,
+            final int inputStyle) {
         // Check if we have a suggestion engine attached.
         if (!settingsValues.needsToLookupSuggestions()) {
             if (mWordComposer.isComposingWord()) {
@@ -1317,8 +1316,8 @@
         }
 
         final AsyncResultHolder<SuggestedWords> holder = new AsyncResultHolder<>();
-        mInputLogicHandler.getSuggestedWords(Suggest.SESSION_TYPING,
-                SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
+        mInputLogicHandler.getSuggestedWords(inputStyle, SuggestedWords.NOT_A_SEQUENCE_NUMBER,
+                new OnGetSuggestedWordsCallback() {
                     @Override
                     public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
                         final String typedWord = mWordComposer.getTypedWord();
@@ -1379,7 +1378,7 @@
         if (!mConnection.isCursorTouchingWord(settingsValues.mSpacingAndPunctuations)) {
             // Show predictions.
             mWordComposer.setCapitalizedModeAtStartComposingTime(WordComposer.CAPS_MODE_OFF);
-            mLatinIME.mHandler.postUpdateSuggestionStrip();
+            mLatinIME.mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_RECORRECTION);
             return;
         }
         final TextRange range = mConnection.getWordRangeAtCursor(
@@ -1444,7 +1443,7 @@
             // 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.
-            mInputLogicHandler.getSuggestedWords(Suggest.SESSION_TYPING,
+            mInputLogicHandler.getSuggestedWords(Suggest.SESSION_ID_TYPING,
                     SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
                         @Override
                         public void onGetSuggestedWords(
@@ -1457,7 +1456,8 @@
                                 // case. The #getSuggestedWordsExcludingTypedWord() method sets
                                 // willAutoCorrect to false.
                                 suggestedWords = suggestedWordsIncludingTypedWord
-                                        .getSuggestedWordsExcludingTypedWord();
+                                        .getSuggestedWordsExcludingTypedWord(SuggestedWords
+                                                .INPUT_STYLE_RECORRECTION);
                             } else {
                                 // No saved suggestions, and we were unable to compute any good one
                                 // either. Rather than displaying an empty suggestion strip, we'll
@@ -1477,6 +1477,7 @@
                     null /* rawSuggestions */, typedWord,
                     false /* typedWordValid */, false /* willAutoCorrect */,
                     false /* isObsoleteSuggestions */, false /* isPrediction */,
+                    SuggestedWords.INPUT_STYLE_RECORRECTION,
                     SuggestedWords.NOT_A_SEQUENCE_NUMBER);
             mIsAutoCorrectionIndicatorOn = false;
             mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
@@ -1773,7 +1774,8 @@
                 SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord, oldSuggestedWords);
         return new SuggestedWords(typedWordAndPreviousSuggestions, null /* rawSuggestions */,
                 false /* typedWordValid */, false /* hasAutoCorrectionCandidate */,
-                true /* isObsoleteSuggestions */, false /* isPrediction */);
+                true /* isObsoleteSuggestions */, false /* isPrediction */,
+                oldSuggestedWords.mInputStyle);
     }
 
     /**
@@ -1956,7 +1958,15 @@
         // Complete any pending suggestions query first
         if (handler.hasPendingUpdateSuggestions()) {
             handler.cancelUpdateSuggestionStrip();
-            performUpdateSuggestionStripSync(settingsValues);
+            // To know the input style here, we should retrieve the in-flight "update suggestions"
+            // message and read its arg1 member here. However, the Handler class does not let
+            // us retrieve this message, so we can't do that. But in fact, we notice that
+            // we only ever come here when the input style was typing. In the case of batch
+            // input, we update the suggestions synchronously when the tail batch comes. Likewise
+            // for application-specified completions. As for recorrections, we never auto-correct,
+            // so we don't come here either. Hence, the input style is necessarily
+            // INPUT_STYLE_TYPING.
+            performUpdateSuggestionStripSync(settingsValues, SuggestedWords.INPUT_STYLE_TYPING);
         }
         final String typedAutoCorrection = mWordComposer.getAutoCorrectionOrNull();
         final String typedWord = mWordComposer.getTypedWord();
@@ -2052,7 +2062,7 @@
     }
 
     public void getSuggestedWords(final SettingsValues settingsValues,
-            final ProximityInfo proximityInfo, final int keyboardShiftMode, final int sessionId,
+            final ProximityInfo proximityInfo, final int keyboardShiftMode, final int inputStyle,
             final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
         mWordComposer.adviseCapitalizedModeBeforeFetchingSuggestions(
                 getActualCapsMode(settingsValues, keyboardShiftMode));
@@ -2068,6 +2078,6 @@
                         settingsValues.mPhraseGestureEnabled,
                         settingsValues.mAdditionalFeaturesSettingValues),
                 settingsValues.mAutoCorrectionEnabledPerUserSettings,
-                sessionId, sequenceNumber, callback);
+                inputStyle, sequenceNumber, callback);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index 9dbe2c3..c6f83d0 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -96,7 +96,7 @@
     public boolean handleMessage(final Message msg) {
         switch (msg.what) {
             case MSG_GET_SUGGESTED_WORDS:
-                mLatinIME.getSuggestedWords(msg.arg1 /* sessionId */,
+                mLatinIME.getSuggestedWords(msg.arg1 /* inputStyle */,
                         msg.arg2 /* sequenceNumber */, (OnGetSuggestedWordsCallback) msg.obj);
                 break;
         }
@@ -134,7 +134,8 @@
                 return;
             }
             mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
-            getSuggestedWords(Suggest.SESSION_GESTURE, sequenceNumber,
+            getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
+                    : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber,
                     new OnGetSuggestedWordsCallback() {
                         @Override
                         public void onGetSuggestedWords(SuggestedWords suggestedWords) {
@@ -205,9 +206,9 @@
         updateBatchInput(batchPointers, sequenceNumber, true /* isTailBatchInput */);
     }
 
-    public void getSuggestedWords(final int sessionId, final int sequenceNumber,
+    public void getSuggestedWords(final int inputStyle, final int sequenceNumber,
             final OnGetSuggestedWordsCallback callback) {
         mNonUIThreadHandler.obtainMessage(
-                MSG_GET_SUGGESTED_WORDS, sessionId, sequenceNumber, callback).sendToTarget();
+                MSG_GET_SUGGESTED_WORDS, inputStyle, sequenceNumber, callback).sendToTarget();
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index dce11b4..63d848e 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -19,6 +19,10 @@
 public final class DebugSettings {
     public static final String PREF_DEBUG_MODE = "debug_mode";
     public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch";
+    public static final String PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY =
+            "force_physical_keyboard_special_key";
+    public static final String PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD =
+            "pref_show_ui_to_accept_typed_word";
     public static final String PREF_KEY_PREVIEW_SHOW_UP_START_SCALE =
             "pref_key_preview_show_up_start_scale";
     public static final String PREF_KEY_PREVIEW_DISMISS_END_SCALE =
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
index 4e41d52..dc2f88a 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
@@ -56,6 +56,10 @@
         super.onCreate(icicle);
         addPreferencesFromResource(R.xml.prefs_screen_debug);
 
+        if (!Settings.HAS_UI_TO_ACCEPT_TYPED_WORD) {
+            removePreference(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD);
+        }
+
         mReadExternalDictionaryPref = findPreference(PREF_READ_EXTERNAL_DICTIONARY);
         if (mReadExternalDictionaryPref != null) {
             mReadExternalDictionaryPref.setOnPreferenceClickListener(this);
@@ -133,7 +137,8 @@
             mServiceNeedsRestart = true;
             return;
         }
-        if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)) {
+        if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)
+                || key.equals(DebugSettings.PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY)) {
             mServiceNeedsRestart = true;
             return;
         }
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 90174e4..9d3c27b 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -24,6 +24,7 @@
 import android.preference.PreferenceManager;
 import android.util.Log;
 
+import com.android.inputmethod.compat.BuildCompatUtils;
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
 import com.android.inputmethod.latin.InputAttributes;
 import com.android.inputmethod.latin.R;
@@ -68,9 +69,9 @@
     public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE =
             "pref_key_block_potentially_offensive";
     public static final boolean ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS =
-            (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
-            || (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT
-                    && Build.VERSION.CODENAME.equals("REL"));
+            BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT;
+    public static final boolean HAS_UI_TO_ACCEPT_TYPED_WORD =
+            BuildCompatUtils.EFFECTIVE_SDK_INT >= BuildCompatUtils.VERSION_CODES_LXX;
     public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY =
             "pref_show_language_switch_key";
     public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 39e834f..c12474b 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -40,7 +40,8 @@
  * When you call the constructor of this class, you may want to change the current system locale by
  * using {@link com.android.inputmethod.latin.utils.RunInLocale}.
  */
-public final class SettingsValues {
+// Non-final for testing via mock library.
+public class SettingsValues {
     private static final String TAG = SettingsValues.class.getSimpleName();
     // "floatMaxValue" and "floatNegativeInfinity" are special marker strings for
     // Float.NEGATIVE_INFINITE and Float.MAX_VALUE. Currently used for auto-correction settings.
@@ -75,6 +76,7 @@
     public final int mKeyLongpressTimeout;
     public final Locale mLocale;
     public final boolean mEnableMetricsLogging;
+    public final boolean mShouldShowUiToAcceptTypedWord;
 
     // From the input box
     public final InputAttributes mInputAttributes;
@@ -142,6 +144,8 @@
         mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
         mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout);
         mEnableMetricsLogging = prefs.getBoolean(Settings.PREF_ENABLE_METRICS_LOGGING, true);
+        mShouldShowUiToAcceptTypedWord = Settings.HAS_UI_TO_ACCEPT_TYPED_WORD
+                && prefs.getBoolean(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD, true);
         // Compute other readable settings
         mKeyLongpressTimeout = Settings.readKeyLongpressTimeout(prefs, res);
         mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res);
@@ -186,6 +190,10 @@
         }
     }
 
+    public boolean isMetricsLoggingEnabled() {
+        return mEnableMetricsLogging;
+    }
+
     public boolean isApplicationSpecifiedCompletionsOn() {
         return mInputAttributes.mApplicationSpecifiedCompletionOn;
     }
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.cpp b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
index b6bf7a9..1e2494e 100644
--- a/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
@@ -19,17 +19,18 @@
 namespace latinime {
 
 const ErrorTypeUtils::ErrorType ErrorTypeUtils::NOT_AN_ERROR = 0x0;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_CASE_ERROR = 0x1;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR = 0x2;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_DIGRAPH = 0x4;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::INTENTIONAL_OMISSION = 0x8;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::EDIT_CORRECTION = 0x10;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::PROXIMITY_CORRECTION = 0x20;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::COMPLETION = 0x40;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::NEW_WORD = 0x80;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_WRONG_CASE = 0x1;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT = 0x2;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT = 0x4;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_DIGRAPH = 0x8;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::INTENTIONAL_OMISSION = 0x10;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::EDIT_CORRECTION = 0x20;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::PROXIMITY_CORRECTION = 0x40;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::COMPLETION = 0x80;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::NEW_WORD = 0x100;
 
 const ErrorTypeUtils::ErrorType ErrorTypeUtils::ERRORS_TREATED_AS_AN_EXACT_MATCH =
-        NOT_AN_ERROR | MATCH_WITH_CASE_ERROR | MATCH_WITH_ACCENT_ERROR | MATCH_WITH_DIGRAPH;
+        NOT_AN_ERROR | MATCH_WITH_WRONG_CASE | MATCH_WITH_MISSING_ACCENT | MATCH_WITH_DIGRAPH;
 
 const ErrorTypeUtils::ErrorType
         ErrorTypeUtils::ERRORS_TREATED_AS_AN_EXACT_MATCH_WITH_INTENTIONAL_OMISSION =
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.h b/native/jni/src/suggest/core/dictionary/error_type_utils.h
index e3e76b2..fd1d5fc 100644
--- a/native/jni/src/suggest/core/dictionary/error_type_utils.h
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.h
@@ -30,8 +30,9 @@
     typedef uint32_t ErrorType;
 
     static const ErrorType NOT_AN_ERROR;
-    static const ErrorType MATCH_WITH_CASE_ERROR;
-    static const ErrorType MATCH_WITH_ACCENT_ERROR;
+    static const ErrorType MATCH_WITH_WRONG_CASE;
+    static const ErrorType MATCH_WITH_MISSING_ACCENT;
+    static const ErrorType MATCH_WITH_WRONG_ACCENT;
     static const ErrorType MATCH_WITH_DIGRAPH;
     // Treat error as an intentional omission when the CorrectionType is omission and the node can
     // be intentional omission.
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 278f2b1..97a8bcc 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
@@ -234,8 +234,8 @@
 bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
         const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
     if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, bigramProperty, outAddedNewEntry)) {
-        AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
-                sourcePtNodeParams->getTerminalId(), targetPtNodeParam->getTerminalId());
+        AKLOGE("Cannot add new bigram entry. prevWordId: %d, wordId: %d",
+                prevWordIds[0], wordId);
         return false;
     }
     const int ptNodePos =
@@ -425,6 +425,18 @@
     return true;
 }
 
+bool Ver4PatriciaTrieNodeWriter::suppressUnigramEntry(const PtNodeParams *const ptNodeParams) {
+    if (!mHeaderPolicy->hasHistoricalInfoOfWords()) {
+        // Require historical info to suppress unigram entry.
+        return false;
+    }
+    const HistoricalInfo suppressedHistorycalInfo(0 /* timestamp */, 0 /* level */, 0 /* count */);
+    const ProbabilityEntry probabilityEntryToWrite =
+            ProbabilityEntry().createEntryWithUpdatedHistoricalInfo(&suppressedHistorycalInfo);
+    return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+            ptNodeParams->getTerminalId(), &probabilityEntryToWrite);
+}
+
 } // namespace v402
 } // namespace backward
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
index d49d9a6..9d8a55b 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
@@ -111,6 +111,11 @@
 
     bool updatePtNodeHasBigramsAndShortcutTargetsFlags(const PtNodeParams *const ptNodeParams);
 
+    // Suppress unigram not to use the word for generating suggestions. So, this method can be used
+    // only for dictionaries with historical info. Also, suppressed entries are included in unigram
+    // count. They will be removed from the dictionary during GC.
+    bool suppressUnigramEntry(const PtNodeParams *const ptNodeParams);
+
  private:
     DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
 
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 1296b8a..9c6452e 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
@@ -210,7 +210,7 @@
     }
     for (const auto &shortcut : unigramProperty->getShortcuts()) {
         if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
-            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %d",
+            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %zd",
                     shortcut.getTargetCodePoints()->size());
             return false;
         }
@@ -245,7 +245,7 @@
                 if (!mUpdatingHelper.addShortcutTarget(wordPos,
                         shortcut.getTargetCodePoints()->data(),
                         shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
-                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %d, "
+                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
                             "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
                             shortcut.getProbability());
                     return false;
@@ -258,6 +258,20 @@
     }
 }
 
+bool Ver4PatriciaTriePolicy::removeUnigramEntry(const int *const word, const int length) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    const int ptNodePos = getTerminalPtNodePositionOfWord(word, length,
+            false /* forceLowerCaseSearch */);
+    if (ptNodePos == NOT_A_DICT_POS) {
+        return false;
+    }
+    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    return mNodeWriter.suppressUnigramEntry(&ptNodeParams);
+}
+
 bool Ver4PatriciaTriePolicy::addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
         const BigramProperty *const bigramProperty) {
     if (!mBuffers->isUpdatable()) {
@@ -275,7 +289,7 @@
     }
     if (bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
         AKLOGE("The word is too long to insert the ngram to the dictionary. "
-                "length: %d", bigramProperty->getTargetCodePoints()->size());
+                "length: %zd", bigramProperty->getTargetCodePoints()->size());
         return false;
     }
     int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
index 9e989b2..d774996 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
@@ -108,10 +108,7 @@
     bool addUnigramEntry(const int *const word, const int length,
             const UnigramProperty *const unigramProperty);
 
-    bool removeUnigramEntry(const int *const word, const int length) {
-        // Removing unigram entry is not supported.
-        return false;
-    }
+    bool removeUnigramEntry(const int *const word, const int length);
 
     bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
             const BigramProperty *const bigramProperty);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
index e4ea3da..9fa93ef 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
@@ -111,8 +111,7 @@
         return nullptr;
     }
     const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::detectFormatVersion(
-            mmappedBuffer->getReadOnlyByteArrayView().data(),
-            mmappedBuffer->getReadOnlyByteArrayView().size());
+            mmappedBuffer->getReadOnlyByteArrayView());
     switch (formatVersion) {
         case FormatUtils::VERSION_2:
             AKLOGE("Given path is a directory but the format is version 2. path: %s", path);
@@ -174,8 +173,7 @@
     if (!mmappedBuffer) {
         return nullptr;
     }
-    switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView().data(),
-            mmappedBuffer->getReadOnlyByteArrayView().size())) {
+    switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView())) {
         case FormatUtils::VERSION_2:
             return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
                     new PatriciaTriePolicy(std::move(mmappedBuffer)));
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 5dc91ba..f3bc4a0 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
@@ -46,7 +46,7 @@
 
 bool LanguageModelDictContent::setNgramProbabilityEntry(const WordIdArrayView prevWordIds,
         const int terminalId, const ProbabilityEntry *const probabilityEntry) {
-    const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
+    const int bitmapEntryIndex = createAndGetBitmapEntryIndex(prevWordIds);
     if (bitmapEntryIndex == TrieMap::INVALID_INDEX) {
         return false;
     }
@@ -80,6 +80,19 @@
     return true;
 }
 
+int LanguageModelDictContent::createAndGetBitmapEntryIndex(const WordIdArrayView prevWordIds) {
+    if (prevWordIds.empty()) {
+        return mTrieMap.getRootBitmapEntryIndex();
+    }
+    const int lastBitmapEntryIndex =
+            getBitmapEntryIndex(prevWordIds.limit(prevWordIds.size() - 1));
+    if (lastBitmapEntryIndex == TrieMap::INVALID_INDEX) {
+        return TrieMap::INVALID_INDEX;
+    }
+    return mTrieMap.getNextLevelBitmapEntryIndex(prevWordIds[prevWordIds.size() - 1],
+            lastBitmapEntryIndex);
+}
+
 int LanguageModelDictContent::getBitmapEntryIndex(const WordIdArrayView prevWordIds) const {
     int bitmapEntryIndex = mTrieMap.getRootBitmapEntryIndex();
     for (const int wordId : prevWordIds) {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
index 18f2e01..104ee25 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
@@ -76,7 +76,7 @@
     bool runGCInner(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
             const TrieMap::TrieMapRange trieMapRange, const int nextLevelBitmapEntryIndex,
             int *const outNgramCount);
-
+    int createAndGetBitmapEntryIndex(const WordIdArrayView prevWordIds);
     int getBitmapEntryIndex(const WordIdArrayView prevWordIds) const;
 };
 } // namespace latinime
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 feff6b5..ed77bd2 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,6 +21,8 @@
 #include <cstdint>
 
 #include "defines.h"
+#include "suggest/core/dictionary/property/bigram_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"
 
@@ -45,6 +47,20 @@
             const HistoricalInfo *const historicalInfo)
             : mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {}
 
+    // Create from unigram property.
+    // TODO: Set flags.
+    ProbabilityEntry(const UnigramProperty *const unigramProperty)
+            : mFlags(0), mProbability(unigramProperty->getProbability()),
+              mHistoricalInfo(unigramProperty->getTimestamp(), unigramProperty->getLevel(),
+                      unigramProperty->getCount()) {}
+
+    // Create from bigram property.
+    // TODO: Set flags.
+    ProbabilityEntry(const BigramProperty *const bigramProperty)
+            : mFlags(0), mProbability(bigramProperty->getProbability()),
+              mHistoricalInfo(bigramProperty->getTimestamp(), bigramProperty->getLevel(),
+                      bigramProperty->getCount()) {}
+
     const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const {
         return ProbabilityEntry(mFlags, probability, &mHistoricalInfo);
     }
@@ -54,6 +70,10 @@
         return ProbabilityEntry(mFlags, mProbability, historicalInfo);
     }
 
+    bool isValid() const {
+        return (mProbability != NOT_A_PROBABILITY) || hasHistoricalInfo();
+    }
+
     bool hasHistoricalInfo() const {
         return mHistoricalInfo.isValid();
     }
@@ -89,7 +109,7 @@
     static ProbabilityEntry decode(const uint64_t encodedEntry, const bool hasHistoricalInfo) {
         if (hasHistoricalInfo) {
             const int flags = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE,
+                    Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE,
                     Ver4DictConstants::TIME_STAMP_FIELD_SIZE
                             + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
                             + Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
@@ -106,7 +126,7 @@
             return ProbabilityEntry(flags, NOT_A_PROBABILITY, &historicalInfo);
         } else {
             const int flags = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE,
+                    Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE,
                     Ver4DictConstants::PROBABILITY_SIZE);
             const int probability = readFromEncodedEntry(encodedEntry,
                     Ver4DictConstants::PROBABILITY_SIZE, 0 /* pos */);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
index 93d4e56..e622442 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
@@ -46,7 +46,7 @@
 
 const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
 const int Ver4DictConstants::PROBABILITY_SIZE = 1;
-const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1;
+const int Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE = 1;
 const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
 const int Ver4DictConstants::NOT_A_TERMINAL_ADDRESS = 0;
 const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
index 6950ca7..8d29f60 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
@@ -41,7 +41,7 @@
 
     static const int NOT_A_TERMINAL_ID;
     static const int PROBABILITY_SIZE;
-    static const int FLAGS_IN_PROBABILITY_FILE_SIZE;
+    static const int FLAGS_IN_LANGUAGE_MODEL_SIZE;
     static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
     static const int NOT_A_TERMINAL_ADDRESS;
     static const int TERMINAL_ID_FIELD_SIZE;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
index 857222f..2c848cb 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
@@ -145,10 +145,11 @@
     const ProbabilityEntry originalProbabilityEntry =
             mBuffers->getLanguageModelDictContent()->getProbabilityEntry(
                     toBeUpdatedPtNodeParams->getTerminalId());
-    const ProbabilityEntry probabilityEntry = createUpdatedEntryFrom(&originalProbabilityEntry,
-            unigramProperty);
+    const ProbabilityEntry probabilityEntryOfUnigramProperty = ProbabilityEntry(unigramProperty);
+    const ProbabilityEntry updatedProbabilityEntry =
+            createUpdatedEntryFrom(&originalProbabilityEntry, &probabilityEntryOfUnigramProperty);
     return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
-            toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry);
+            toBeUpdatedPtNodeParams->getTerminalId(), &updatedProbabilityEntry);
 }
 
 bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
@@ -216,16 +217,36 @@
     }
     // Write probability.
     ProbabilityEntry newProbabilityEntry;
+    const ProbabilityEntry probabilityEntryOfUnigramProperty = ProbabilityEntry(unigramProperty);
     const ProbabilityEntry probabilityEntryToWrite = createUpdatedEntryFrom(
-            &newProbabilityEntry, unigramProperty);
+            &newProbabilityEntry, &probabilityEntryOfUnigramProperty);
     return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
             terminalId, &probabilityEntryToWrite);
 }
 
 bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
         const BigramProperty *const bigramProperty, bool *const outAddedNewBigram) {
+    // TODO: Support n-gram.
+    LanguageModelDictContent *const languageModelDictContent =
+            mBuffers->getMutableLanguageModelDictContent();
+    const ProbabilityEntry probabilityEntry =
+            languageModelDictContent->getNgramProbabilityEntry(
+                    prevWordIds.limit(1 /* maxSize */), wordId);
+    const ProbabilityEntry probabilityEntryOfBigramProperty(bigramProperty);
+    const ProbabilityEntry updatedProbabilityEntry = createUpdatedEntryFrom(
+            &probabilityEntry, &probabilityEntryOfBigramProperty);
+    if (!languageModelDictContent->setNgramProbabilityEntry(
+            prevWordIds.limit(1 /* maxSize */), wordId, &updatedProbabilityEntry)) {
+        AKLOGE("Cannot add new ngram entry. prevWordId: %d, wordId: %d",
+                prevWordIds[0], wordId);
+        return false;
+    }
+    if (!probabilityEntry.isValid() && outAddedNewBigram) {
+        *outAddedNewBigram = true;
+    }
+    // TODO: Remove.
     if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, bigramProperty, outAddedNewBigram)) {
-        AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
+        AKLOGE("Cannot add new bigram entry. prevWordId: %d, wordId: %d",
                 prevWordIds[0], wordId);
         return false;
     }
@@ -234,6 +255,7 @@
 
 bool Ver4PatriciaTrieNodeWriter::removeNgramEntry(const WordIdArrayView prevWordIds,
         const int wordId) {
+    // TODO: Remove.
     return mBigramPolicy->removeEntry(prevWordIds[0], wordId);
 }
 
@@ -352,20 +374,19 @@
 
 const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
         const ProbabilityEntry *const originalProbabilityEntry,
-        const UnigramProperty *const unigramProperty) const {
+        const ProbabilityEntry *const probabilityEntry) const {
     // TODO: Consolidate historical info and probability.
     if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(unigramProperty->getTimestamp(),
-                unigramProperty->getLevel(), unigramProperty->getCount());
         const HistoricalInfo updatedHistoricalInfo =
                 ForgettingCurveUtils::createUpdatedHistoricalInfo(
                         originalProbabilityEntry->getHistoricalInfo(),
-                        unigramProperty->getProbability(), &historicalInfoForUpdate, mHeaderPolicy);
+                        probabilityEntry->getProbability(), probabilityEntry->getHistoricalInfo(),
+                        mHeaderPolicy);
         return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo(
                 &updatedHistoricalInfo);
     } else {
         return originalProbabilityEntry->createEntryWithUpdatedProbability(
-                unigramProperty->getProbability());
+                probabilityEntry->getProbability());
     }
 }
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
index 6703dba..5d73b6e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
@@ -98,12 +98,12 @@
             const PtNodeParams *const ptNodeParams, int *const outTerminalId,
             int *const ptNodeWritingPos);
 
-    // Create updated probability entry using given unigram property. In addition to the
+    // Create updated probability entry using given probability property. In addition to the
     // probability, this method updates historical information if needed.
-    // TODO: Update flags belonging to the unigram property.
+    // TODO: Update flags.
     const ProbabilityEntry createUpdatedEntryFrom(
             const ProbabilityEntry *const originalProbabilityEntry,
-            const UnigramProperty *const unigramProperty) const;
+            const ProbabilityEntry *const probabilityEntry) const;
 
     bool updatePtNodeFlags(const int ptNodePos, const bool isBlacklisted, const bool isNotAWord,
             const bool isTerminal, const bool hasMultipleChars);
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 7238083..d8f4595 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
@@ -200,7 +200,7 @@
     }
     for (const auto &shortcut : unigramProperty->getShortcuts()) {
         if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
-            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %d",
+            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %zd",
                     shortcut.getTargetCodePoints()->size());
             return false;
         }
@@ -235,7 +235,7 @@
                 if (!mUpdatingHelper.addShortcutTarget(wordPos,
                         shortcut.getTargetCodePoints()->data(),
                         shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
-                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %d, "
+                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
                             "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
                             shortcut.getProbability());
                     return false;
@@ -286,7 +286,7 @@
     }
     if (bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
         AKLOGE("The word is too long to insert the ngram to the dictionary. "
-                "length: %d", bigramProperty->getTargetCodePoints()->size());
+                "length: %zd", bigramProperty->getTargetCodePoints()->size());
         return false;
     }
     int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
index 1916ea5..e6e7167 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
@@ -23,7 +23,7 @@
 const uint32_t FormatUtils::MAGIC_NUMBER = 0x9BC13AFE;
 
 // Magic number (4 bytes), version (2 bytes), flags (2 bytes), header size (4 bytes) = 12
-const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
+const size_t FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
 
 /* static */ FormatUtils::FORMAT_VERSION FormatUtils::getFormatVersion(const int formatVersion) {
     switch (formatVersion) {
@@ -40,14 +40,14 @@
     }
 }
 /* static */ FormatUtils::FORMAT_VERSION FormatUtils::detectFormatVersion(
-        const uint8_t *const dict, const int dictSize) {
+        const ReadOnlyByteArrayView dictBuffer) {
     // The magic number is stored big-endian.
     // If the dictionary is less than 4 bytes, we can't even read the magic number, so we don't
     // understand this format.
-    if (dictSize < DICTIONARY_MINIMUM_SIZE) {
+    if (dictBuffer.size() < DICTIONARY_MINIMUM_SIZE) {
         return UNKNOWN_VERSION;
     }
-    const uint32_t magicNumber = ByteArrayUtils::readUint32(dict, 0);
+    const uint32_t magicNumber = ByteArrayUtils::readUint32(dictBuffer.data(), 0);
     switch (magicNumber) {
         case MAGIC_NUMBER:
             // The layout of the header is as follows:
@@ -58,7 +58,7 @@
             // Conceptually this converts the hardcoded value of the bytes in the file into
             // the symbolic value we use in the code. But we want the constants to be the
             // same so we use them for both here.
-            return getFormatVersion(ByteArrayUtils::readUint16(dict, 4));
+            return getFormatVersion(ByteArrayUtils::readUint16(dictBuffer.data(), 4));
         default:
             return UNKNOWN_VERSION;
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
index 55ad579..51ad987 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
@@ -20,6 +20,7 @@
 #include <cstdint>
 
 #include "defines.h"
+#include "utils/byte_array_view.h"
 
 namespace latinime {
 
@@ -42,12 +43,12 @@
     static const uint32_t MAGIC_NUMBER;
 
     static FORMAT_VERSION getFormatVersion(const int formatVersion);
-    static FORMAT_VERSION detectFormatVersion(const uint8_t *const dict, const int dictSize);
+    static FORMAT_VERSION detectFormatVersion(const ReadOnlyByteArrayView dictBuffer);
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(FormatUtils);
 
-    static const int DICTIONARY_MINIMUM_SIZE;
+    static const size_t DICTIONARY_MINIMUM_SIZE;
 };
 } // namespace latinime
 #endif /* LATINIME_FORMAT_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
index 407b8ef..e630aba 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
@@ -26,6 +26,7 @@
 const int TrieMap::ENTRY_SIZE = FIELD0_SIZE + FIELD1_SIZE;
 const uint32_t TrieMap::VALUE_FLAG = 0x400000;
 const uint32_t TrieMap::VALUE_MASK = 0x3FFFFF;
+const uint32_t TrieMap::INVALID_VALUE_IN_KEY_VALUE_ENTRY = VALUE_MASK;
 const uint32_t TrieMap::TERMINAL_LINK_FLAG = 0x800000;
 const uint32_t TrieMap::TERMINAL_LINK_MASK = 0x7FFFFF;
 const int TrieMap::NUM_OF_BITS_USED_FOR_ONE_LEVEL = 5;
@@ -34,6 +35,7 @@
 const int TrieMap::ROOT_BITMAP_ENTRY_INDEX = 0;
 const int TrieMap::ROOT_BITMAP_ENTRY_POS = MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL * FIELD0_SIZE;
 const TrieMap::Entry TrieMap::EMPTY_BITMAP_ENTRY = TrieMap::Entry(0, 0);
+const int TrieMap::TERMINAL_LINKED_ENTRY_COUNT = 2; // Value entry and bitmap entry.
 const uint64_t TrieMap::MAX_VALUE =
         (static_cast<uint64_t>(1) << ((FIELD0_SIZE + FIELD1_SIZE) * CHAR_BIT)) - 1;
 const int TrieMap::MAX_BUFFER_SIZE = TERMINAL_LINK_MASK * ENTRY_SIZE;
@@ -76,7 +78,7 @@
         return terminalEntry.getValueEntryIndex() + 1;
     }
     // Create a value entry and a bitmap entry.
-    const int valueEntryIndex = allocateTable(2 /* entryCount */);
+    const int valueEntryIndex = allocateTable(TERMINAL_LINKED_ENTRY_COUNT);
     if (!writeEntry(Entry(0, terminalEntry.getValue()), valueEntryIndex)) {
         return INVALID_INDEX;
     }
@@ -108,6 +110,31 @@
     return DictFileWritingUtils::writeBufferToFileTail(file, &mBuffer);
 }
 
+bool TrieMap::remove(const int key, const int bitmapEntryIndex) {
+    const Entry bitmapEntry = readEntry(bitmapEntryIndex);
+    const uint32_t unsignedKey = static_cast<uint32_t>(key);
+    const int terminalEntryIndex = getTerminalEntryIndex(
+            unsignedKey, getBitShuffledKey(unsignedKey), bitmapEntry, 0 /* level */);
+    if (terminalEntryIndex == INVALID_INDEX) {
+        // Not found.
+        return false;
+    }
+    const Entry terminalEntry = readEntry(terminalEntryIndex);
+    if (!writeField1(VALUE_FLAG ^ INVALID_VALUE_IN_KEY_VALUE_ENTRY , terminalEntryIndex)) {
+        return false;
+    }
+    if (terminalEntry.hasTerminalLink()) {
+        const Entry nextLevelBitmapEntry = readEntry(terminalEntry.getValueEntryIndex() + 1);
+        if (!freeTable(terminalEntry.getValueEntryIndex(), TERMINAL_LINKED_ENTRY_COUNT)) {
+            return false;
+        }
+        if (!removeInner(nextLevelBitmapEntry)){
+            return false;
+        }
+    }
+    return true;
+}
+
 /**
  * Iterate next entry in a certain level.
  *
@@ -129,7 +156,7 @@
             if (entry.isBitmapEntry()) {
                 // Move to child.
                 iterationState->emplace_back(popCount(entry.getBitmap()), entry.getTableIndex());
-            } else {
+            } else if (entry.isValidTerminalEntry()) {
                 if (outKey) {
                     *outKey = entry.getKey();
                 }
@@ -162,12 +189,12 @@
 }
 
 bool TrieMap::writeValue(const uint64_t value, const int terminalEntryIndex) {
-    if (value <= VALUE_MASK) {
+    if (value < VALUE_MASK) {
         // Write value into the terminal entry.
         return writeField1(value | VALUE_FLAG, terminalEntryIndex);
     }
     // Create value entry and write value.
-    const int valueEntryIndex = allocateTable(2 /* entryCount */);
+    const int valueEntryIndex = allocateTable(TERMINAL_LINKED_ENTRY_COUNT);
     if (!writeEntry(Entry(value >> (FIELD1_SIZE * CHAR_BIT), value), valueEntryIndex)) {
         return false;
     }
@@ -227,6 +254,9 @@
         // Move to the next level.
         return getTerminalEntryIndex(key, hashedKey, entry, level + 1);
     }
+    if (!entry.isValidTerminalEntry()) {
+        return INVALID_INDEX;
+    }
     if (entry.getKey() == key) {
         // Terminal entry is found.
         return entryIndex;
@@ -287,6 +317,10 @@
         // Bitmap entry is found. Go to the next level.
         return putInternal(key, value, hashedKey, entryIndex, entry, level + 1);
     }
+    if (!entry.isValidTerminalEntry()) {
+        // Overwrite invalid terminal entry.
+        return writeTerminalEntry(key, value, entryIndex);
+    }
     if (entry.getKey() == key) {
         // Terminal entry for the key is found. Update the value.
         return updateValue(entry, value, entryIndex);
@@ -384,4 +418,33 @@
     return true;
 }
 
+bool TrieMap::removeInner(const Entry &bitmapEntry) {
+    const int tableSize = popCount(bitmapEntry.getBitmap());
+    for (int i = 0; i < tableSize; ++i) {
+        const int entryIndex = bitmapEntry.getTableIndex() + i;
+        const Entry entry = readEntry(entryIndex);
+        if (entry.isBitmapEntry()) {
+            // Delete next bitmap entry recursively.
+            if (!removeInner(entry)) {
+                return false;
+            }
+        } else {
+            // Invalidate terminal entry just in case.
+            if (!writeField1(VALUE_FLAG ^ INVALID_VALUE_IN_KEY_VALUE_ENTRY , entryIndex)) {
+                return false;
+            }
+            if (entry.hasTerminalLink()) {
+                const Entry nextLevelBitmapEntry = readEntry(entry.getValueEntryIndex() + 1);
+                if (!freeTable(entry.getValueEntryIndex(), TERMINAL_LINKED_ENTRY_COUNT)) {
+                    return false;
+                }
+                if (!removeInner(nextLevelBitmapEntry)) {
+                    return false;
+                }
+            }
+        }
+    }
+    return freeTable(bitmapEntry.getTableIndex(), tableSize);
+}
+
 }  // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
index 3e5c401..6d91790 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
@@ -202,6 +202,8 @@
 
     bool save(FILE *const file) const;
 
+    bool remove(const int key, const int bitmapEntryIndex);
+
  private:
     DISALLOW_COPY_AND_ASSIGN(TrieMap);
 
@@ -245,6 +247,11 @@
         }
 
         // For terminal entry.
+        AK_FORCE_INLINE bool isValidTerminalEntry() const {
+            return hasTerminalLink() || ((mData1 & VALUE_MASK) != INVALID_VALUE_IN_KEY_VALUE_ENTRY);
+        }
+
+        // For terminal entry.
         AK_FORCE_INLINE uint32_t getValueEntryIndex() const {
             return mData1 & TERMINAL_LINK_MASK;
         }
@@ -272,6 +279,7 @@
     static const int ENTRY_SIZE;
     static const uint32_t VALUE_FLAG;
     static const uint32_t VALUE_MASK;
+    static const uint32_t INVALID_VALUE_IN_KEY_VALUE_ENTRY;
     static const uint32_t TERMINAL_LINK_FLAG;
     static const uint32_t TERMINAL_LINK_MASK;
     static const int NUM_OF_BITS_USED_FOR_ONE_LEVEL;
@@ -280,6 +288,7 @@
     static const int ROOT_BITMAP_ENTRY_INDEX;
     static const int ROOT_BITMAP_ENTRY_POS;
     static const Entry EMPTY_BITMAP_ENTRY;
+    static const int TERMINAL_LINKED_ENTRY_COUNT;
     static const int MAX_BUFFER_SIZE;
 
     uint32_t getBitShuffledKey(const uint32_t key) const;
@@ -378,6 +387,8 @@
     AK_FORCE_INLINE int getTailEntryIndex() const {
         return (mBuffer.getTailPosition() - ROOT_BITMAP_ENTRY_POS) / ENTRY_SIZE;
     }
+
+    bool removeInner(const Entry &bitmapEntry);
 };
 
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
index 04cb660..52c4251 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
@@ -51,10 +51,10 @@
         }
         if (boostExactMatches && ErrorTypeUtils::isExactMatch(containedErrorTypes)) {
             score += ScoringParams::EXACT_MATCH_PROMOTION;
-            if ((ErrorTypeUtils::MATCH_WITH_CASE_ERROR & containedErrorTypes) != 0) {
+            if ((ErrorTypeUtils::MATCH_WITH_WRONG_CASE & containedErrorTypes) != 0) {
                 score -= ScoringParams::CASE_ERROR_PENALTY_FOR_EXACT_MATCH;
             }
-            if ((ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR & containedErrorTypes) != 0) {
+            if ((ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT & containedErrorTypes) != 0) {
                 score -= ScoringParams::ACCENT_ERROR_PENALTY_FOR_EXACT_MATCH;
             }
             if ((ErrorTypeUtils::MATCH_WITH_DIGRAPH & containedErrorTypes) != 0) {
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
index 54f65c7..1d590c3 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
@@ -36,25 +36,34 @@
                 // Compare the node code point with original primary code point on the keyboard.
                 const ProximityInfoState *const pInfoState =
                         traverseSession->getProximityInfoState(0);
-                const int primaryOriginalCodePoint = pInfoState->getPrimaryOriginalCodePointAt(
+                const int primaryCodePoint = pInfoState->getPrimaryCodePointAt(
                         dicNode->getInputIndex(0));
                 const int nodeCodePoint = dicNode->getNodeCodePoint();
-                if (primaryOriginalCodePoint == nodeCodePoint) {
+                // TODO: Check whether the input code point is on the keyboard.
+                if (primaryCodePoint == nodeCodePoint) {
                     // Node code point is same as original code point on the keyboard.
                     return ErrorTypeUtils::NOT_AN_ERROR;
-                } else if (CharUtils::toLowerCase(primaryOriginalCodePoint) ==
+                } else if (CharUtils::toLowerCase(primaryCodePoint) ==
                         CharUtils::toLowerCase(nodeCodePoint)) {
                     // Only cases of the code points are different.
-                    return ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
-                } else if (CharUtils::toBaseCodePoint(primaryOriginalCodePoint) ==
-                        CharUtils::toBaseCodePoint(nodeCodePoint)) {
+                    return ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
+                } else if (primaryCodePoint == CharUtils::toBaseCodePoint(nodeCodePoint)) {
                     // Node code point is a variant of original code point.
-                    return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR;
-                } else {
+                    return ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT;
+                } else if (CharUtils::toBaseCodePoint(primaryCodePoint)
+                        == CharUtils::toBaseCodePoint(nodeCodePoint)) {
+                    // Base code points are the same but the code point is intentionally input.
+                    return ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT;
+                } else if (CharUtils::toLowerCase(primaryCodePoint)
+                        == CharUtils::toBaseLowerCase(nodeCodePoint)) {
                     // Node code point is a variant of original code point and the cases are also
                     // different.
-                    return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR
-                            | ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
+                    return ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT
+                            | ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
+                } else {
+                    // Base code points are the same and the cases are different.
+                    return ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT
+                            | ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
                 }
             }
             break;
diff --git a/native/jni/src/utils/int_array_view.h b/native/jni/src/utils/int_array_view.h
index c1ddc98..53f2d29 100644
--- a/native/jni/src/utils/int_array_view.h
+++ b/native/jni/src/utils/int_array_view.h
@@ -91,6 +91,11 @@
         return mPtr + mSize;
     }
 
+    // Returns the view whose size is smaller than or equal to the given count.
+    const IntArrayView limit(const size_t maxSize) const {
+        return IntArrayView(mPtr, std::min(maxSize, mSize));
+    }
+
  private:
     DISALLOW_ASSIGNMENT_OPERATOR(IntArrayView);
 
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp
index df778b6..8c8e883 100644
--- a/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp
+++ b/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp
@@ -47,6 +47,31 @@
     EXPECT_EQ(0xFFFFFFFFFull, trieMap.getRoot(0).mValue);
 }
 
+TEST(TrieMapTest, TestRemove) {
+    TrieMap trieMap;
+    trieMap.putRoot(10, 10);
+    EXPECT_EQ(10ull, trieMap.getRoot(10).mValue);
+    EXPECT_TRUE(trieMap.remove(10, trieMap.getRootBitmapEntryIndex()));
+    EXPECT_FALSE(trieMap.getRoot(10).mIsValid);
+    for (const auto &element : trieMap.getEntriesInRootLevel()) {
+        EXPECT_TRUE(false);
+    }
+    EXPECT_TRUE(trieMap.putRoot(10, 0x3FFFFF));
+    EXPECT_FALSE(trieMap.remove(11, trieMap.getRootBitmapEntryIndex()))
+            << "Should fail if the key does not exist.";
+    EXPECT_EQ(0x3FFFFFull, trieMap.getRoot(10).mValue);
+    trieMap.putRoot(12, 11);
+    const int nextLevel = trieMap.getNextLevelBitmapEntryIndex(10);
+    trieMap.put(10, 10, nextLevel);
+    EXPECT_EQ(0x3FFFFFull, trieMap.getRoot(10).mValue);
+    EXPECT_EQ(10ull, trieMap.get(10, nextLevel).mValue);
+    EXPECT_TRUE(trieMap.remove(10, trieMap.getRootBitmapEntryIndex()));
+    const TrieMap::Result result = trieMap.getRoot(10);
+    EXPECT_FALSE(result.mIsValid);
+    EXPECT_EQ(TrieMap::INVALID_INDEX, result.mNextLevelBitmapEntryIndex);
+    EXPECT_EQ(11ull, trieMap.getRoot(12).mValue);
+}
+
 TEST(TrieMapTest, TestSetAndGetLarge) {
     static const int ELEMENT_COUNT = 200000;
     TrieMap trieMap;
diff --git a/native/jni/tests/utils/int_array_view_test.cpp b/native/jni/tests/utils/int_array_view_test.cpp
index bd843ab..ecc451a 100644
--- a/native/jni/tests/utils/int_array_view_test.cpp
+++ b/native/jni/tests/utils/int_array_view_test.cpp
@@ -53,9 +53,24 @@
 TEST(IntArrayViewTest, TestConstructFromObject) {
     const int object = 10;
     const auto intArrayView = IntArrayView::fromObject(&object);
-    EXPECT_EQ(1, intArrayView.size());
+    EXPECT_EQ(1u, intArrayView.size());
     EXPECT_EQ(object, intArrayView[0]);
 }
 
+TEST(IntArrayViewTest, TestLimit) {
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+
+    EXPECT_TRUE(intArrayView.limit(0).empty());
+    EXPECT_EQ(intArrayView.size(), intArrayView.limit(intArrayView.size()).size());
+    EXPECT_EQ(intArrayView.size(), intArrayView.limit(1000).size());
+
+    IntArrayView subView = intArrayView.limit(4);
+    EXPECT_EQ(4u, subView.size());
+    for (size_t i = 0; i < subView.size(); ++i) {
+        EXPECT_EQ(intVector[i], subView[i]);
+    }
+}
+
 }  // namespace
 }  // namespace latinime
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
index 0c7e400..c20954f 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard;
 
+import static com.android.inputmethod.compat.BuildCompatUtils.VERSION_CODES_LXX;
 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_ICS;
 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_KLP;
 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_LXX_DARK;
@@ -31,9 +32,6 @@
 public class KeyboardThemeTests extends AndroidTestCase {
     private SharedPreferences mPrefs;
 
-    // TODO: Remove this constant once the *next* version becomes available.
-    private static final int VERSION_CODES_LXX = VERSION_CODES.CUR_DEVELOPMENT;
-
     private static final int THEME_ID_NULL = -1;
     private static final int THEME_ID_UNKNOWN = -2;
     private static final int THEME_ID_ILLEGAL = -3;
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java b/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
index 42ce0c1..dba91b4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
@@ -39,6 +39,9 @@
         public ArmenianPhoneticCustomizer(final Locale locale) { super(locale); }
 
         @Override
+        public int getNumberOfRows() { return 5; }
+
+        @Override
         public ExpectedKey getAlphabetKey() { return ARMENIAN_ALPHABET_KEY; }
 
         @Override
@@ -112,29 +115,6 @@
         return builder.build();
     }
 
-    // Helper method to create alphabet layout by adding special function keys.
-    @Override
-    ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
-            final boolean isPhone) {
-        final LayoutCustomizer customizer = getCustomizer();
-        builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
-        builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
-        builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
-        if (isPhone) {
-            builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
-        } else {
-            builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
-                    .addKeysOnTheRightOfRow(3, ENTER_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, EMOJI_KEY);
-        }
-        builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
-                .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
-        return builder;
-    }
-
     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
             .setKeysOfRow(1,
                     // U+0567: "է" ARMENIAN SMALL LETTER EH
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java b/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
index 143ccf6..7e4f159 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
@@ -40,6 +40,9 @@
         public KhmerCustomizer(final Locale locale) { super(locale); }
 
         @Override
+        public int getNumberOfRows() { return 5; }
+
+        @Override
         public ExpectedKey getAlphabetKey() { return KHMER_ALPHABET_KEY; }
 
         @Override
@@ -79,29 +82,6 @@
         return ALPHABET_SHIFTED_COMMON;
     }
 
-    // Helper method to create alphabet layout by adding special function keys.
-    @Override
-    ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
-            final boolean isPhone) {
-        final LayoutCustomizer customizer = getCustomizer();
-        builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
-        builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
-        builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
-        if (isPhone) {
-            builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
-        } else {
-            builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
-                    .addKeysOnTheRightOfRow(3, ENTER_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, EMOJI_KEY);
-        }
-        builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
-                .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
-        return builder;
-    }
-
     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
             .setKeysOfRow(1,
                     // U+17E1: "១" KHMER DIGIT ONE
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Lao.java b/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
index e7be998..aaa1c8a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
@@ -40,6 +40,9 @@
         public LaoCustomizer(final Locale locale) { super(locale); }
 
         @Override
+        public int getNumberOfRows() { return 5; }
+
+        @Override
         public ExpectedKey getAlphabetKey() { return LAO_ALPHABET_KEY; }
 
         @Override
@@ -83,29 +86,6 @@
         return ALPHABET_SHIFTED_COMMON;
     }
 
-    // Helper method to create alphabet layout by adding special function keys.
-    @Override
-    ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
-            final boolean isPhone) {
-        final LayoutCustomizer customizer = getCustomizer();
-        builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
-        builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
-        builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
-        if (isPhone) {
-            builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
-        } else {
-            builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
-                    .addKeysOnTheRightOfRow(3, ENTER_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, EMOJI_KEY);
-        }
-        builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
-                .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
-        return builder;
-    }
-
     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
             .setKeysOfRow(1,
                     // U+0EA2: "ຢ" LAO LETTER YO
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
index c522372..0548a01 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
@@ -46,6 +46,10 @@
             return mLocale;
         }
 
+        public int getNumberOfRows() {
+            return 4;
+        }
+
         /**
          * Set accented letters to common layout.
          * @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
@@ -277,7 +281,7 @@
             ",", "'", "#", ")", "(", "/", ";",
             "@", ":", "-", "\"", "+", "%", "&");
 
-   /**
+    /**
      * Helper method to create alphabet layout adding special function keys.
      * @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
      *     layout
@@ -287,21 +291,26 @@
     ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
             final boolean isPhone) {
         final LayoutCustomizer customizer = getCustomizer();
-        builder.setKeysOfRow(4, (Object[])customizer.getSpaceKeys(isPhone));
-        builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
-        builder.addKeysOnTheRightOfRow(4, (Object[])customizer.getKeysRightToSpacebar(isPhone));
+        final int numberOfRows = customizer.getNumberOfRows();
+        builder.setKeysOfRow(numberOfRows, (Object[])customizer.getSpaceKeys(isPhone));
+        builder.addKeysOnTheLeftOfRow(
+                numberOfRows, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
+        builder.addKeysOnTheRightOfRow(
+                numberOfRows, (Object[])customizer.getKeysRightToSpacebar(isPhone));
         if (isPhone) {
-            builder.addKeysOnTheRightOfRow(3, DELETE_KEY)
-                    .addKeysOnTheLeftOfRow(4, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY));
+            builder.addKeysOnTheRightOfRow(numberOfRows - 1, DELETE_KEY)
+                    .addKeysOnTheLeftOfRow(numberOfRows, customizer.getSymbolsKey())
+                    .addKeysOnTheRightOfRow(numberOfRows, key(ENTER_KEY, EMOJI_ACTION_KEY));
         } else {
             builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
-                    .addKeysOnTheRightOfRow(2, ENTER_KEY)
-                    .addKeysOnTheLeftOfRow(4, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(4, EMOJI_KEY);
+                    .addKeysOnTheRightOfRow(numberOfRows - 2, ENTER_KEY)
+                    .addKeysOnTheLeftOfRow(numberOfRows, customizer.getSymbolsKey())
+                    .addKeysOnTheRightOfRow(numberOfRows, EMOJI_NORMAL_KEY);
         }
-        builder.addKeysOnTheLeftOfRow(3, (Object[])customizer.getLeftShiftKeys(isPhone))
-                .addKeysOnTheRightOfRow(3, (Object[])customizer.getRightShiftKeys(isPhone));
+        builder.addKeysOnTheLeftOfRow(
+                numberOfRows - 1, (Object[])customizer.getLeftShiftKeys(isPhone));
+        builder.addKeysOnTheRightOfRow(
+                numberOfRows - 1, (Object[])customizer.getRightShiftKeys(isPhone));
         return builder;
     }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java b/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
index f2a2dfd..15c74ed 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
@@ -40,6 +40,9 @@
         public MyanmarCustomizer(final Locale locale) { super(locale); }
 
         @Override
+        public int getNumberOfRows() { return 5; }
+
+        @Override
         public ExpectedKey getAlphabetKey() { return MYANMAR_ALPHABET_KEY; }
 
         @Override
@@ -97,29 +100,6 @@
         return ALPHABET_SHIFTED_COMMON;
     }
 
-    // Helper method to create alphabet layout by adding special function keys.
-    @Override
-    ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
-            final boolean isPhone) {
-        final LayoutCustomizer customizer = getCustomizer();
-        builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
-        builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
-        builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
-        if (isPhone) {
-            builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
-        } else {
-            builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
-                    .addKeysOnTheRightOfRow(3, ENTER_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, EMOJI_KEY);
-        }
-        builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
-                .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
-        return builder;
-    }
-
     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
             .setKeysOfRow(1,
                     // U+1041: "၁" MYANMAR DIGIT ONE
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
index 9da6dcc..3f7340f 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
@@ -39,6 +39,9 @@
         public PcQwertyCustomizer(final Locale locale) { super(locale); }
 
         @Override
+        public int getNumberOfRows() { return 5; }
+
+        @Override
         public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
             return joinKeys(SHIFT_KEY);
         }
@@ -55,7 +58,9 @@
 
         @Override
         public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            return isPhone ? joinKeys(key(ENTER_KEY, EMOJI_KEY)) : joinKeys(EMOJI_KEY);
+            return isPhone
+                    ? joinKeys(key(ENTER_KEY, EMOJI_ACTION_KEY))
+                    : joinKeys(EMOJI_NORMAL_KEY);
         }
     }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
index 5f3e4b1..2cee2d9 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
@@ -43,7 +43,7 @@
             builder.addKeysOnTheLeftOfRow(3, customizer.getSymbolsShiftKey(isPhone))
                     .addKeysOnTheRightOfRow(3, DELETE_KEY)
                     .addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
-                    .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY));
+                    .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_ACTION_KEY));
         } else {
             // Tablet symbols keyboard has extra two keys at the left edge of the 3rd row.
             builder.addKeysOnTheLeftOfRow(3, (Object[])joinKeys("\\", "="));
@@ -52,7 +52,7 @@
                     .addKeysOnTheLeftOfRow(3, customizer.getSymbolsShiftKey(isPhone))
                     .addKeysOnTheRightOfRow(3, customizer.getSymbolsShiftKey(isPhone))
                     .addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
-                    .addKeysOnTheRightOfRow(4, EMOJI_KEY);
+                    .addKeysOnTheRightOfRow(4, EMOJI_NORMAL_KEY);
         }
         return builder.build();
     }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
index 3265e10..7ed103b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
@@ -39,7 +39,7 @@
             builder.addKeysOnTheLeftOfRow(3, customizer.getBackToSymbolsKey())
                     .addKeysOnTheRightOfRow(3, DELETE_KEY)
                     .addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
-                    .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY));
+                    .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_ACTION_KEY));
         } else {
             // Tablet symbols shifted keyboard has extra two keys at the right edge of the 3rd row.
             // U+00BF: "¿" INVERTED QUESTION MARK
@@ -50,7 +50,7 @@
                     .addKeysOnTheLeftOfRow(3, customizer.getBackToSymbolsKey())
                     .addKeysOnTheRightOfRow(3, customizer.getBackToSymbolsKey())
                     .addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
-                    .addKeysOnTheRightOfRow(4, EMOJI_KEY);
+                    .addKeysOnTheRightOfRow(4, EMOJI_NORMAL_KEY);
         }
         return builder.build();
     }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Thai.java b/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
index af4abea..cfda294 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
@@ -40,6 +40,9 @@
         public ThaiCustomizer(final Locale locale) { super(locale); }
 
         @Override
+        public int getNumberOfRows() { return 5; }
+
+        @Override
         public ExpectedKey getAlphabetKey() { return THAI_ALPHABET_KEY; }
 
         @Override
@@ -96,29 +99,6 @@
         return builder.build();
     }
 
-    // Helper method to create alphabet layout by adding special function keys.
-    @Override
-    ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
-            final boolean isPhone) {
-        final LayoutCustomizer customizer = getCustomizer();
-        builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
-        builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
-        builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
-        if (isPhone) {
-            builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
-        } else {
-            builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
-                    .addKeysOnTheRightOfRow(3, ENTER_KEY)
-                    .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
-                    .addKeysOnTheRightOfRow(5, EMOJI_KEY);
-        }
-        builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
-                .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
-        return builder;
-    }
-
     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
             .setKeysOfRow(1,
                     // U+0E45: "ๅ" THAI CHARACTER LAKKHANGYAO
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
index 9e0039d..0f7bef2 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
@@ -120,8 +120,10 @@
             KeyboardIconsSet.NAME_LANGUAGE_SWITCH_KEY);
     private static final int ICON_ENTER = KeyboardIconsSet.getIconId(
             KeyboardIconsSet.NAME_ENTER_KEY);
-    private static final int ICON_EMOJI = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_EMOJI_KEY);
+    private static final int ICON_EMOJI_ACTION = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_EMOJI_ACTION_KEY);
+    private static final int ICON_EMOJI_NORMAL = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY);
 
     // Functional keys.
     public static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE);
@@ -131,6 +133,7 @@
     public static final ExpectedKey LANGUAGE_SWITCH_KEY = key(
             ICON_LANGUAGE_SWITCH, Constants.CODE_LANGUAGE_SWITCH);
     public static final ExpectedKey ENTER_KEY = key(ICON_ENTER, Constants.CODE_ENTER);
-    public static final ExpectedKey EMOJI_KEY = key(ICON_EMOJI, Constants.CODE_EMOJI);
+    public static final ExpectedKey EMOJI_ACTION_KEY = key(ICON_EMOJI_ACTION, Constants.CODE_EMOJI);
+    public static final ExpectedKey EMOJI_NORMAL_KEY = key(ICON_EMOJI_NORMAL, Constants.CODE_EMOJI);
     public static final ExpectedKey SPACE_KEY = key(ICON_SPACE, Constants.CODE_SPACE);
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
index f937de8..b494ad3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
@@ -25,7 +25,7 @@
 import java.util.Locale;
 
 /**
- * ta_IN: Malayalam (India)/malayalam
+ * ml_IN: Malayalam (India)/malayalam
  */
 @SmallTest
 public final class TestsMalayalamIN extends LayoutTestsBase {
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index ae18426..342eb29 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -689,4 +689,36 @@
         binaryDictionary.close();
         dictFile.delete();
     }
+
+    public void testRemoveUnigrams() {
+        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+            testRemoveUnigrams(formatVersion);
+        }
+    }
+
+    private void testRemoveUnigrams(final int formatVersion) {
+        final int unigramInputCount = 20;
+        setCurrentTimeForTestMode(mCurrentTime);
+        File dictFile = null;
+        try {
+            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
+        } catch (IOException e) {
+            fail("IOException while writing an initial dictionary : " + e);
+        }
+        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+        addUnigramWord(binaryDictionary, "aaa", Dictionary.NOT_A_PROBABILITY);
+        assertFalse(binaryDictionary.isValidWord("aaa"));
+        for (int i = 0; i < unigramInputCount; i++) {
+            addUnigramWord(binaryDictionary, "aaa", Dictionary.NOT_A_PROBABILITY);
+        }
+        assertTrue(binaryDictionary.isValidWord("aaa"));
+        assertTrue(binaryDictionary.removeUnigramEntry("aaa"));
+        assertFalse(binaryDictionary.isValidWord("aaa"));
+
+        binaryDictionary.close();
+        dictFile.delete();
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index 66b4a9c..a5f20b5 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -48,7 +48,8 @@
                 false /* typedWordValid */,
                 false /* willAutoCorrect */,
                 false /* isObsoleteSuggestions */,
-                false /* isPrediction*/);
+                false /* isPrediction*/,
+                SuggestedWords.INPUT_STYLE_NONE);
         assertEquals(NUMBER_OF_ADDED_SUGGESTIONS + 1, words.size());
         assertEquals("typed", words.getWord(0));
         assertTrue(words.getInfo(0).isKindOf(SuggestedWordInfo.KIND_TYPED));
@@ -57,7 +58,8 @@
         assertEquals("4", words.getWord(5));
         assertTrue(words.getInfo(5).isKindOf(SuggestedWordInfo.KIND_CORRECTION));
 
-        final SuggestedWords wordsWithoutTyped = words.getSuggestedWordsExcludingTypedWord();
+        final SuggestedWords wordsWithoutTyped = words.getSuggestedWordsExcludingTypedWord(
+                SuggestedWords.INPUT_STYLE_NONE);
         assertEquals(words.size() - 1, wordsWithoutTyped.size());
         assertEquals("0", wordsWithoutTyped.getWord(0));
         assertTrue(wordsWithoutTyped.getInfo(0).isKindOf(SuggestedWordInfo.KIND_CORRECTION));
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index f87f3b4..abb468f 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -28,6 +28,7 @@
 import com.android.inputmethod.latin.utils.FileUtils;
 
 import java.io.File;
+import java.io.FilenameFilter;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -41,6 +42,8 @@
 @LargeTest
 public class UserHistoryDictionaryTests extends AndroidTestCase {
     private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
+    private static final int WAIT_FOR_WRITING_FILE_IN_MILLISECONDS = 3000;
+    private static final String TEST_LOCALE_PREFIX = "test_";
 
     private static final String[] CHARACTERS = {
         "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
@@ -49,14 +52,55 @@
 
     private int mCurrentTime = 0;
 
+    private void removeAllTestDictFiles() {
+        final Locale dummyLocale = new Locale(TEST_LOCALE_PREFIX);
+        final String dictName = ExpandableBinaryDictionary.getDictName(
+                UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
+        final File dictFile = ExpandableBinaryDictionary.getDictFile(
+                mContext, dictName, null /* dictFile */);
+        final FilenameFilter filenameFilter = new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String filename) {
+                return filename.startsWith(UserHistoryDictionary.NAME + "." + TEST_LOCALE_PREFIX);
+            }
+        };
+        FileUtils.deleteFilteredFiles(dictFile.getParentFile(), filenameFilter);
+    }
+
+    private void printAllFiles(final File dir) {
+        Log.d(TAG, dir.getAbsolutePath());
+        for (final File file : dir.listFiles()) {
+            Log.d(TAG, "  " + file.getName());
+        }
+    }
+
+    private void checkExistenceAndRemoveDictFile(final Locale locale, final File dictFile) {
+        Log.d(TAG, "waiting for writing ...");
+        waitForWriting(locale);
+        if (!dictFile.exists()) {
+            try {
+                Log.d(TAG, dictFile + " is not existing. Wait "
+                        + WAIT_FOR_WRITING_FILE_IN_MILLISECONDS + " ms for writing.");
+                printAllFiles(dictFile.getParentFile());
+                Thread.sleep(WAIT_FOR_WRITING_FILE_IN_MILLISECONDS);
+            } catch (final InterruptedException e) {
+                Log.e(TAG, "Interrupted during waiting for writing the dict file.");
+            }
+        }
+        assertTrue("check exisiting of " + dictFile, dictFile.exists());
+        FileUtils.deleteRecursively(dictFile);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         resetCurrentTimeForTestMode();
+        removeAllTestDictFiles();
     }
 
     @Override
     protected void tearDown() throws Exception {
+        removeAllTestDictFiles();
         stopTestModeInNativeCode();
         super.tearDown();
     }
@@ -168,7 +212,8 @@
     public void testRandomWords() {
         Log.d(TAG, "This test can be used for profiling.");
         Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true.");
-        final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
+        final Locale dummyLocale =
+                new Locale(TEST_LOCALE_PREFIX + "random_words" + System.currentTimeMillis());
         final String dictName = ExpandableBinaryDictionary.getDictName(
                 UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
         final File dictFile = ExpandableBinaryDictionary.getDictFile(
@@ -182,10 +227,7 @@
             addAndWriteRandomWords(dummyLocale, numberOfWords, random,
                     true /* checksContents */);
         } finally {
-            Log.d(TAG, "waiting for writing ...");
-            waitForWriting(dummyLocale);
-            assertTrue("check exisiting of " + dictFile, dictFile.exists());
-            FileUtils.deleteRecursively(dictFile);
+            checkExistenceAndRemoveDictFile(dummyLocale, dictFile);
         }
     }
 
@@ -201,7 +243,7 @@
 
             // Create filename suffixes for this test.
             for (int i = 0; i < numberOfLanguages; i++) {
-                dummyLocales[i] = new Locale("test_switching_languages" + i);
+                dummyLocales[i] = new Locale(TEST_LOCALE_PREFIX + "switching_languages" + i);
                 final String dictName = ExpandableBinaryDictionary.getDictName(
                         UserHistoryDictionary.NAME, dummyLocales[i], null /* dictFile */);
                 dictFiles[i] = ExpandableBinaryDictionary.getDictFile(
@@ -223,19 +265,15 @@
             Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took "
                     + (end - start) + " ms");
         } finally {
-            Log.d(TAG, "waiting for writing ...");
             for (int i = 0; i < numberOfLanguages; i++) {
-                waitForWriting(dummyLocales[i]);
-            }
-            for (final File dictFile : dictFiles) {
-                assertTrue("check exisiting of " + dictFile, dictFile.exists());
-                FileUtils.deleteRecursively(dictFile);
+                checkExistenceAndRemoveDictFile(dummyLocales[i], dictFiles[i]);
             }
         }
     }
 
     public void testAddManyWords() {
-        final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
+        final Locale dummyLocale =
+                new Locale(TEST_LOCALE_PREFIX + "many_random_words" + System.currentTimeMillis());
         final String dictName = ExpandableBinaryDictionary.getDictName(
                 UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
         final File dictFile = ExpandableBinaryDictionary.getDictFile(
@@ -246,15 +284,13 @@
         try {
             addAndWriteRandomWords(dummyLocale, numberOfWords, random, true /* checksContents */);
         } finally {
-            Log.d(TAG, "waiting for writing ...");
-            waitForWriting(dummyLocale);
-            assertTrue("check exisiting of " + dictFile, dictFile.exists());
-            FileUtils.deleteRecursively(dictFile);
+            checkExistenceAndRemoveDictFile(dummyLocale, dictFile);
         }
     }
 
     public void testDecaying() {
-        final Locale dummyLocale = new Locale("test_decaying" + System.currentTimeMillis());
+        final Locale dummyLocale =
+                new Locale(TEST_LOCALE_PREFIX + "decaying" + System.currentTimeMillis());
         final int numberOfWords = 5000;
         final Random random = new Random(123456);
         resetCurrentTimeForTestMode();
diff --git a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
index bf97e73..c4a1b88 100644
--- a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
@@ -258,5 +258,5 @@
     <string name="morekeys_single_quote">!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes</string>
     <string name="morekeys_double_quote">!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes</string>
     <string name="morekeys_tablet_double_quote">!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes</string>
-    <string name="keyspec_emoji_key">!icon/emoji_key|!code/key_emoji</string>
+    <string name="keyspec_emoji_action_key">!icon/emoji_action_key|!code/key_emoji</string>
 </resources>