Merge "Import translations. DO NOT MERGE"
diff --git a/java/res/layout/emoji_palettes_view.xml b/java/res/layout/emoji_palettes_view.xml
index a6ea38b..26cc042 100644
--- a/java/res/layout/emoji_palettes_view.xml
+++ b/java/res/layout/emoji_palettes_view.xml
@@ -20,10 +20,10 @@
 
 <com.android.inputmethod.keyboard.emoji.EmojiPalettesView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/emoji_keyboard_view"
-    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_gravity="bottom"
+    android:orientation="vertical"
     style="?attr/emojiPalettesViewStyle"
 >
     <LinearLayout
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml
index a4bcdcc..46551f6 100644
--- a/java/res/layout/input_view.xml
+++ b/java/res/layout/input_view.xml
@@ -21,38 +21,11 @@
 <com.android.inputmethod.latin.InputView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:gravity="bottom|center_horizontal"
-    android:orientation="vertical" >
-    <!-- The height of key_preview_backing view will automatically be determined by code. -->
-    <FrameLayout
-        android:id="@+id/key_preview_backing"
-        android:layout_width="match_parent"
-        android:layout_height="0dp" />
-    <LinearLayout
-        android:id="@+id/main_keyboard_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical" >
-
-        <!-- To ensure that key preview popup is correctly placed when the current system locale is
-             one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
-        <com.android.inputmethod.latin.suggestions.SuggestionStripView
-            android:id="@+id/suggestion_strip_view"
-            android:layoutDirection="ltr"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/config_suggestions_strip_height"
-            android:gravity="center_vertical"
-            style="?attr/suggestionStripViewStyle" />
-
-        <!-- To ensure that key preview popup is correctly placed when the current system locale is
-             one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
-        <com.android.inputmethod.keyboard.MainKeyboardView
-            android:id="@+id/keyboard_view"
-            android:layoutDirection="ltr"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-    </LinearLayout>
+    android:layout_height="wrap_content">
     <include
+        android:id="@+id/main_keyboard_frame"
+        layout="@layout/main_keyboard_frame" />
+    <include
+        android:id="@+id/emoji_palettes_view"
         layout="@layout/emoji_palettes_view" />
 </com.android.inputmethod.latin.InputView>
diff --git a/java/res/layout/main_keyboard_frame.xml b/java/res/layout/main_keyboard_frame.xml
new file mode 100644
index 0000000..ebf7466
--- /dev/null
+++ b/java/res/layout/main_keyboard_frame.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="bottom"
+    android:orientation="vertical" >
+
+    <!-- To ensure that key preview popup is correctly placed when the current system locale is
+         one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
+    <com.android.inputmethod.latin.suggestions.SuggestionStripView
+        android:id="@+id/suggestion_strip_view"
+        android:layoutDirection="ltr"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/config_suggestions_strip_height"
+        android:gravity="center_vertical"
+        style="?attr/suggestionStripViewStyle" />
+
+    <!-- To ensure that key preview popup is correctly placed when the current system locale is
+         one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
+    <com.android.inputmethod.keyboard.MainKeyboardView
+        android:id="@+id/keyboard_view"
+        android:layoutDirection="ltr"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+</LinearLayout>
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index c1b7b76..e90e543 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Raak hier om te stoor"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordeboek beskikbaar"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Sleutelbordtema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engels (VK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spaans (VS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engels (VK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engels (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spaans (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisioneel)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillies)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latyns)"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 15440fc..34f4890 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ለማስቀመጥ እዚህ ይንኩ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"መዝገበ ቃላት አለ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"የቁልፍ ሰሌዳ ገጽታ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"እንግሊዘኛ (የታላቋ ብሪታንያ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"እንግሊዘኛ (ዩ.ኤስ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ስፓኒሽኛ (ዩኤስ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ሂንግሊሽ"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"እንግሊዝኛ (ዩኬ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"እንግሊዝኛ (አሜሪካ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ስፓኒሽ (አሜሪካ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ሂንግሊሽ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ተለምዷዊ)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ሳይሪሊክ)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ላቲን)"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index b6252c8..2b4686b 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"المس هنا للحفظ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"القاموس متاح"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"مظهر لوحة المفاتيح"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"الإنجليزية (المملكة المتحدة)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"الإنجليزية (الولايات المتحدة)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"الإسبانية (الأميركية)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"هنجليزية"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"الإنجليزية (المملكة المتحدة) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"الإنجليزية (الولايات المتحدة) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"الإسبانية (الولايات المتحدة) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"هنجليزية (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (التقليدية)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (السريلية)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (اللاتينية)"</string>
diff --git a/java/res/values-az-rAZ/strings.xml b/java/res/values-az-rAZ/strings.xml
index 1d11e84..2487748 100644
--- a/java/res/values-az-rAZ/strings.xml
+++ b/java/res/values-az-rAZ/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Yadda saxlamaq üçün buraya toxunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Lüğət mövcuddur"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatura teması"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"İngilis (BK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"İngilis (ABŞ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"İspan (ABŞ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hingilis"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"İngilis (Britaniya) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"İngilis (Amerika) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"İspan (Amerika) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hingilis (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Ənənəvi)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kiril)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latın)"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index f4af1db..1ead030 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Докоснете тук, за да запазите"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Има достъп до речник"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема на клавиатурата"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"английски (Великобритания)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"английски (САЩ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"испански (САЩ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"английски (Великобр.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"английски (САЩ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"испански (САЩ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционна клавиатура)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кирилица)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
diff --git a/java/res/values-bn-rBD/strings.xml b/java/res/values-bn-rBD/strings.xml
index b52409e..f8ea9ad 100644
--- a/java/res/values-bn-rBD/strings.xml
+++ b/java/res/values-bn-rBD/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"সংরক্ষণ করতে এখানে স্পর্শ করুন"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"অভিধান উপলব্ধ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"কীবোর্ড থিম"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ইংরেজি (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ইংরেজি (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"স্প্যানিশ (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"হিংলিশ"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ইংরেজি (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ইংরেজি (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"স্প্যানিশ (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"হিংলিশ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ঐতিহ্যবাহি)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (সিরিলিক)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ল্যাটিন)"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 2fab1b7..e37bd05 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda i opinió"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toca aquí per desar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionari disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclat"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglès (Regne Unit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglès (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espanyol (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Anglès (Regne Unit) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Anglès (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Espanyol (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ciríl·lic)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (llatí)"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 265e457..883fbdf 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Nápověda a zpětná vazba"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Klepnutím sem položku uložíte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovník k dispozici"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Motiv klávesnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angličtina (Velká Británie)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angličtina (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španělština (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angličtina (VB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angličtina (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španělština (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradiční)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrilice)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinka)"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 2e7c88a..caaafcc 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Hjælp og feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Inputsprog"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Klik her for at gemme"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannien)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spansk (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engelsk (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engelsk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spansk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionelt)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisk)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index cf4c554..0a6155a 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Hilfe &amp; Feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Eingabesprachen"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Zum Speichern erneut berühren"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tippen Sie hier zum Speichern."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfügbar"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturdesign"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Englisch (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Englisch (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanisch (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Englisch (GB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Englisch (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanisch (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionell)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisch)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (lateinisch)"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 239541f..825af72 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Αγγίξτε εδώ για αποθήκευση"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Λεξικό διαθέσιμο"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Θέμα πληκτρολογίου"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Αγγλικά (Η.Β.)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Αγγλικά (Η.Π.Α)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Ισπανικά (ΗΠΑ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Αγγλικά (Ηνωμένο Βασίλειο) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Αγγλικά (ΗΠΑ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Ισπανικά (ΗΠΑ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Παραδοσιακά)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Κυριλλικά)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Λατινικά)"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index a8a7ade..a671c2a 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Touch here to save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"English (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"English (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillic)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
diff --git a/java/res/values-en-rIN/strings.xml b/java/res/values-en-rIN/strings.xml
index a8a7ade..a671c2a 100644
--- a/java/res/values-en-rIN/strings.xml
+++ b/java/res/values-en-rIN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Touch here to save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"English (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"English (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillic)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 84135ef..b643d5a 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Ayuda y comentarios"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tocar aquí para guardar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglés (EE.UU.)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Español (EE.UU.)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglés, Reino Unido (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglés, EE. UU. (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Español, EE. UU. (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirílico)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latinoamérica)"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 98b985b..07b4bff 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Ayuda y opiniones"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toca aquí para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema de teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"inglés (EE.UU.)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Español (EE.UU.)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglés (Reino Unido) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglés (EE.UU.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Español (EE.UU.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirílico)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latinoamérica)"</string>
diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml
index 042f7cf..c4f940b 100644
--- a/java/res/values-et-rEE/strings.xml
+++ b/java/res/values-et-rEE/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Abi ja tagasiside"</string>
     <string name="select_language" msgid="3693815588777926848">"Sisestuskeeled"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Salvestamiseks puudutage uuesti"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Salvestamiseks puudutage siin"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sõnastik saadaval"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatuuri teema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglise (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglise (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"hispaania (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi-inglise"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglise (Ühendk.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglise (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Hispaania (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi-inglise (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditsiooniline)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kirillitsa)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ladina)"</string>
diff --git a/java/res/values-eu-rES/strings.xml b/java/res/values-eu-rES/strings.xml
index f3128ae..f3704ad 100644
--- a/java/res/values-eu-rES/strings.xml
+++ b/java/res/values-eu-rES/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Laguntza eta iritziak"</string>
     <string name="select_language" msgid="3693815588777926848">"Idazketa-hizkuntzak"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gordetzeko, ukitu berriro"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Gordetzeko, ukitu hau"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hiztegia erabilgarri"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Teklatuaren gaia"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Ingelesa (Erresuma Batua)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Ingelesa (AEB)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Gaztelania (AEB)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglisha"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ingelesa (Erresuma Batua) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ingelesa (AEB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Gaztelania (AEB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglisha (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradizionala)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (zirilikoa)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latindarra)"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index ff68313..dbde38f 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"برای ذخیره اینجا را لمس کنید"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"دیکشنری موجود است"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"طرح زمینه صفحه‌کلید"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"انگلیسی (بریتانیا)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"انگلیسی (امریکا)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"اسپانیایی (آمریکا)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"هندی انگلیسی"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"انگلیسی (بریتانیا) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"انگلیسی (آمریکا) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"اسپانیایی (آمریکا) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"هندی انگلیسی (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (سنتی)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (سیریلیک)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (لاتین)"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 1f06b07..1dbdb5a 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tallenna koskettamalla tätä"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sanakirja saatavilla"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Näppäimistöteema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"englanti (Iso-Britannia)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"englanti (Yhdysvallat)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"espanja (Yhdysvallat)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindienglanti"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"englanti (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"englanti (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"espanja (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindienglanti (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (perinteinen)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillinen)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinalainen)"</string>
diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml
index e2cf8cf..dbfb588 100644
--- a/java/res/values-fr-rCA/strings.xml
+++ b/java/res/values-fr-rCA/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Aide et commentaires"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Touchez ici pour enregistrer le mot dans le dictionnaire"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (britannique)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (États-Unis)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espagnol (États-Unis)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"anglais (Royaume-Uni) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"anglais (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"espagnol (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionnel)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrillique)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 75961d1..3a308f9 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Aide et commentaires"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Appuyez ici pour enregistrer."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (Royaume-Uni)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (États-Unis)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espagnol (États-Unis)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi/Anglais"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"anglais (Royaume-Uni) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"anglais (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"espagnol (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi/Anglais (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionnel)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrillique)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
diff --git a/java/res/values-gl-rES/strings.xml b/java/res/values-gl-rES/strings.xml
index 40431e7..9b24949 100644
--- a/java/res/values-gl-rES/strings.xml
+++ b/java/res/values-gl-rES/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Axuda e opinións"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toca aquí para gardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionario dispoñible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglés (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Español (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglés (Reino Unido) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglés (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Español (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirílico)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latino)"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 86d5130..ab6eb81 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"सहेजने के लिए यहां स्पर्श करें"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"शब्‍दकोश उपलब्‍ध है"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"कीबोर्ड थीम"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"अंग्रेज़ी (यूके)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"अंग्रेज़ी (यूएस)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"स्पेनिश (यूएस)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"हिंग्लिश"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"अंग्रेज़ी (यूके) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"अंग्रेज़ी (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"स्‍पेनिश (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिंग्लिश (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (पारंपरिक)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (सिरिलिक)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (लैटिन)"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index d6b1352..668d6c5 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Pomoć i povratne informacije"</string>
     <string name="select_language" msgid="3693815588777926848">"Jezici unosa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dodirnite ponovo za spremanje"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Dodirnite ovdje za spremanje"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Rječnik je dostupan"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engleski (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engleski (SAD)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španjolski (SAD)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"engleska (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"engleska (SAD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španjolska (SAD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionalni)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ćirilica)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinica)"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index b38d1bf..4560788 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Súgó és visszajelzés"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"A mentéshez érintse meg itt"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Van elérhető szótár"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Billentyűzettéma"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angol (brit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angol (amerikai)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"spanyol (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish (hindi-angol)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angol (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angol (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"spanyol (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (hindi-angol, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (hagyományos)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirill)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
diff --git a/java/res/values-hy-rAM/strings.xml b/java/res/values-hy-rAM/strings.xml
index 26a3b02..1e14263 100644
--- a/java/res/values-hy-rAM/strings.xml
+++ b/java/res/values-hy-rAM/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Պահելու համար հպեք այստեղ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Բառարանն առկա է"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Ստեղնաշարի թեման"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Անգլերեն (ՄԹ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Անգլերեն (ԱՄՆ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Իսպաներեն (ԱՄՆ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Հինգլիշ"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Անգլերեն (ՄԹ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Անգլերեն (ԱՄՆ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Իսպաներեն (ԱՄՆ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Հինգլիշ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ավանդական)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (կյուրեղյան)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (լատինական)"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 9c898b7..0169995 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Bantuan &amp; masukan"</string>
     <string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Sentuh di sini untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus yang tersedia"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema keyboard"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inggris (Inggris)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inggris (AS)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanyol (AS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>) Inggris (Inggris)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>) Inggris (AS)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>) Spanyol (AS)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Sirilik)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
diff --git a/java/res/values-is-rIS/strings.xml b/java/res/values-is-rIS/strings.xml
index 8d46c89..51f4f9b 100644
--- a/java/res/values-is-rIS/strings.xml
+++ b/java/res/values-is-rIS/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Hjálp og ábendingar"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Snertu hér til að vista"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Orðabók í boði"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Þema lyklaborðs"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Enskt (Bretland)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Enskt (Bandaríkin)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spænskt (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Enskt (Bretland) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Enskt (Bandaríkin) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spænskt (Bandaríkin) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (hefðbundið)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillískt)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latneskt)"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 4f81588..32a9e37 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tocca qui per salvare"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema della tastiera"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglese (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglese (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spagnolo (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglese (Regno Unito) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglese (Stati Uniti) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spagnolo (Stati Uniti) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradizionale)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cirillico)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latino)"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 4f331a3..be4f8fe 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"גע כאן כדי לשמור"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"מילון זמין"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"עיצוב מקלדת"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"אנגלית (בריטניה)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"אנגלית (ארה\"ב)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ספרדית (ארצות הברית)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"אנגלית הודית"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"אנגלית (בריטניה)‏ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"אנגלית (ארה\"ב) ‏(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ספרדית (ארה\"ב) ‏(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"אנגלית הודית (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (מסורתית)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (קירילית)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (לטינית)"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 97f84e7..26da044 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ここをタップして保存します"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"辞書を利用できます"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"キーボードのテーマ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英語 (英国)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英語 (米国)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"スペイン語 (米国)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ヒングリッシュ"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英語(英国)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"英語(米国)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"スペイン語(米国)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ヒングリッシュ(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(伝統言語)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(キリル文字)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(ラテン文字)"</string>
diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml
index a42b6df..784edd2 100644
--- a/java/res/values-ka-rGE/strings.xml
+++ b/java/res/values-ka-rGE/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"აქ შეეხეთ, რომ შეინახოს"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ხელმისაწვდომია ლექსიკონი"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"კლავიატურის თემა"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ინგლისური (გართ. სამ.)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ინგლისური (აშშ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ესპანური (აშშ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ჰინგლისური"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ინგლისური (გაერთ.სამ.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ინგლისური (აშშ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ესპანური (აშშ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ჰინგლისური (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ტრადიციული)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (კირილიცა)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ლათინური)"</string>
diff --git a/java/res/values-kk-rKZ/strings.xml b/java/res/values-kk-rKZ/strings.xml
index 64ee430..490c357 100644
--- a/java/res/values-kk-rKZ/strings.xml
+++ b/java/res/values-kk-rKZ/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Сақтау үшін осы жерді түртіңіз"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Сөздік қолжетімді"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Пернетақта тақырыбы"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ағылшын (ҰБ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ағылшын (АҚШ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Испан (АҚШ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ағылшын (Құрама Корольдік) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ағылшын (АҚШ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испан (АҚШ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (дәстүрлі)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кириллица)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 2ea86b9..31efc8b 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>
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ប៉ះ​ទីនេះ​ដើម្បី​រក្សាទុក"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"មាន​វចនានុក្រម"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"រូបរាង​ក្ដារចុច"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"អង់គ្លេស (​អង់គ្លេស)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"អង់គ្លេស (សហរដ្ឋ​អាមេរិក)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"អេស្ប៉ាញ (សហរដ្ឋ​អាមេរិក​)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"អង់គ្លេស (ចក្រភព​អង់គ្លេស) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"អង់គ្លេស (អាមេរិក) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"អេស្ប៉ាញ (អាមេរិក) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (អក្សរ​ពេញ)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ស៊ីរី)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ឡាតាំង)"</string>
@@ -115,7 +118,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 +145,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 +161,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 +182,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 4fcf06f..4a9bd52 100644
--- a/java/res/values-kn-rIN/strings.xml
+++ b/java/res/values-kn-rIN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ಉಳಿಸಲು ಇಲ್ಲಿ ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ನಿಘಂಟು ಲಭ್ಯವಿದೆ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ಕೀಬೋರ್ಡ್ ಥೀಮ್"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ಇಂಗ್ಲಿಷ್ (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ಇಂಗ್ಲಿಷ್ (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ಸ್ಪ್ಯಾನಿಷ್ (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ಹಿಂಗ್ಲಿಷ್"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ಇಂಗ್ಲಿಷ್ (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ಇಂಗ್ಲಿಷ್ (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ಸ್ಪ್ಯಾನಿಷ್ (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ಹಿಂಗ್ಲಿಷ್ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಸಾಂಪ್ರದಾಯಿಕ)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಸಿರಿಲಿಕ್)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಲ್ಯಾಟಿನ್)"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 73f8f86..12ca801 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"저장하려면 여기를 터치하세요."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"사전 사용 가능"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"키보드 테마"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"영어(영국)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"영어(미국)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"스페인어(미국)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"인도 영어"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"영어(영국)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"영어(미국)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"스페인어(미국)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"인도 영어(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(번체)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(키릴어)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(라틴어)"</string>
diff --git a/java/res/values-ky-rKG/strings.xml b/java/res/values-ky-rKG/strings.xml
index ad8317d..6552aff 100644
--- a/java/res/values-ky-rKG/strings.xml
+++ b/java/res/values-ky-rKG/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Сактоо үчүн бул жерди басыңыз"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Сөздүк бар"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Баскычтоп темасы"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Англисче (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Англисче (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Испанча (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Англисче (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Англисче (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испанча (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Салттык)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Кирилл)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Латын)"</string>
diff --git a/java/res/values-lo-rLA/strings.xml b/java/res/values-lo-rLA/strings.xml
index eed5380..906bd3e 100644
--- a/java/res/values-lo-rLA/strings.xml
+++ b/java/res/values-lo-rLA/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ແຕະ​ບ່ອນ​ນີ້​ເພື່ອ​ບັນ​ທຶກ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ມີວັດຈະນານຸກົມ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ສີສັນແປ້ນພິມ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ອັງກິດ (ສະຫະລາດຊະອານາຈັກ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ອັງກິດ (ສະຫະລັດຯ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ສະເປນ (ອາເມລິກາ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ຮິງ​ລິສ"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ອັງ​ກິດ (ສະ​ຫະ​ລາດ​ຊະ​ອາ​ນາ​ຈັກ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ອັງ​ກິດ (ສະ​ຫະ​ລັດຯ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ສະ​ແປນ​ນິດ (ສະ​ຫະ​ລັດຯ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ຮິງ​ລິສ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ດັ້ງ​ເດີມ)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ຊິ​ຣິວ​ລິກ)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ລາ​ຕິນ)"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index c1ef8aa..0e4b316 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Palieskite čia, kad išsaugotumėte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Žodynas galimas"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatūros tema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglų k. (JK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglų k. (JAV)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Ispanų k. (JAV)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi ir anglų k. derinys"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Anglų (JK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Anglų (JAV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Ispanų (JAV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi ir anglų derinys (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicinė)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kirilica)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (lotynų)"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 5878982..80dd00c 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Palīdzība un atsauksmes"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Lai saglabātu, pieskarieties šeit"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ir pieejama vārdnīca."</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastatūras motīvs"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Angļu valoda (Lielbritānija)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Angļu valoda (ASV)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spāņu (ASV)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi–angļu valoda"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Angļu (Lielbritānija) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Angļu (ASV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spāņu (ASV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi–angļu valoda (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionālā)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kirilica)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latīņu)"</string>
diff --git a/java/res/values-mk-rMK/strings.xml b/java/res/values-mk-rMK/strings.xml
index 3c6d872..7ef9ff3 100644
--- a/java/res/values-mk-rMK/strings.xml
+++ b/java/res/values-mk-rMK/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Допри тука да се зачува"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Речникот е достапен"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема на тастатурата"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"англиски (ОК)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"англиски (САД)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"шпански (САД)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"англиски (ОК) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"англиски (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"шпански (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционален)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кирилица)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
diff --git a/java/res/values-ml-rIN/strings.xml b/java/res/values-ml-rIN/strings.xml
index 5826eab..b87c0af 100644
--- a/java/res/values-ml-rIN/strings.xml
+++ b/java/res/values-ml-rIN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"സംരക്ഷിക്കാൻ ഇവിടെ സ്‌പർശിക്കുക"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"നിഘണ്ടു ലഭ്യമാണ്"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"കീബോർഡ് തീം"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ഇംഗ്ലീഷ് (യുകെ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ഇംഗ്ലീഷ് (യുഎസ്)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"സ്‌പാനിഷ് (യുഎസ്)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ഹിംഗ്ലീഷ്"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ഇംഗ്ലീഷ് (യുകെ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ഇംഗ്ലീഷ് (യുഎസ്) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"സ്‌പാനിഷ് (യുഎസ്) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ഹിംഗ്ലീഷ് (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (പരമ്പരാഗതം)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (സിറിലിക്)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ലാറ്റിൻ)"</string>
diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml
index db04f60..f922c0e 100644
--- a/java/res/values-mn-rMN/strings.xml
+++ b/java/res/values-mn-rMN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Хадгалахын тулд хүрнэ үү"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Толь бичиг байна"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Гарын загвар"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Англи (ИБ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Англи (АНУ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Испани (АНУ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Англи (ИБ) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Англи (АНУ) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испани (АНУ-ын) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (уламжлалт)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Кирилл)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Латин)"</string>
diff --git a/java/res/values-mr-rIN/strings.xml b/java/res/values-mr-rIN/strings.xml
index 677438c..c950e28 100644
--- a/java/res/values-mr-rIN/strings.xml
+++ b/java/res/values-mr-rIN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"जतन करण्यासाठी येथे स्पर्श करा"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"शब्दकोश उपलब्ध"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"कीबोर्ड थीम"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"इंग्रजी (यूके)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"इंग्रजी (यूएस)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"स्पॅनिश (यूएस)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"हिंग्लिश"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"इंग्रजी (यूके) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"इंग्रजी (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"स्पॅनिश (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिंग्लिश (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (पारंपारिक)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (सिरिलिक)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (लॅटिन)"</string>
diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml
index 758ff10..a07e77d 100644
--- a/java/res/values-ms-rMY/strings.xml
+++ b/java/res/values-ms-rMY/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Bantuan &amp; m/balas"</string>
     <string name="select_language" msgid="3693815588777926848">"Bahasa input"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Sentuh di sini untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus tersedia"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema papan kekunci"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Bahasa Inggeris (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Bahasa Inggeris (Australia)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Bahasa Sepanyol (AS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Bahasa Inggeris (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Bahasa Inggeris (AS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Bahasa Sepanyol (AS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyril)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</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 6862124..f07d887 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,18 +76,21 @@
     <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="language_selection_title" msgid="1651299598555326750">"ထည့်သွင်းမှု ဘာသာ"</string>
     <string name="help_and_feedback" msgid="5328219371839879161">"အကူအညီ &amp; တုံ့ပြန်ချက်"</string>
-    <string name="select_language" msgid="3693815588777926848">"ထည့်သွင်းမှု ဘာသာ"</string>
+    <string name="select_language" msgid="3693815588777926848">"ထည့်သွင်းမှု ဘာသာ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"သိမ်းရန် နောက်တစ်ကြိမ်နှိပ်ပါ"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"သိမ်းရန် ဤနေရာကို ထိပါ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"အဘိဓါန်ရနိုင်"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ကီးဘုတ်အရောင်"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"အင်္ဂလိပ်(ယူကေ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"အင်္ဂလိပ် (ယူအက်စ်)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"စပိန် (ယူအက်စ်)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ဟင်ဂလိပ်"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"အင်္ဂလိပ် (ယူကေ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"အင်္ဂလိပ် (ယူအက်စ်) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"စပိန် (ယူအက်စ်) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ဟင်ဂလိပ် (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ရိုးရာ)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ဗျည်းအက္ခရာ)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (လက်တင်)"</string>
@@ -149,7 +152,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 +166,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 +187,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 e450717..fcc5c97 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Hjelp og tilbakemelding"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Trykk her for å lagre"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannia)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spansk (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engelsk (Storbritannia) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engelsk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spansk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradisjonelt)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisk)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
diff --git a/java/res/values-ne-rNP/strings.xml b/java/res/values-ne-rNP/strings.xml
index 926ae13..c7c95ae 100644
--- a/java/res/values-ne-rNP/strings.xml
+++ b/java/res/values-ne-rNP/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"बचत गर्न यहाँ छुनुहोस्"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"उपलब्ध शब्दकोश"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"किबोर्ड थिम"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"अंग्रेजी (युके)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"अंग्रेजी (युएस्)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"स्पेनिस (युएस्)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"हिङ्लिस"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"अंग्रेजी (बेलायत) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"अंग्रेजी (अमेरिका) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"स्पेनेली (अमेरिका) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिङ्लिस (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (परम्परागत)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (सिरिलिक)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ल्याटिन)"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index aa4aca8..8ee5e4b 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Help en feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Invoertalen"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tik nogmaals om op te slaan"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tik hier om op te slaan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Toetsenbordthema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engels (GB)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spaans (VS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi-Engels"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engels (VK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engels (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spaans (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi-Engels (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditioneel)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillisch)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latijns)"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 2c709ad..70fb091 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Pomoc i opinie"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Kliknij tutaj, by zapisać"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Słownik dostępny"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Motyw klawiatury"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angielski (Wielka Brytania)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angielski (Stany Zjednoczone)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"hiszpański (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Angielski (Wielka Brytania) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Angielski (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Hiszpański (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradycyjny)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrylica)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (alfabet łaciński)"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 9bd407e..9c3bc4c 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda e comentários"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toque aqui para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (RU)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espanhol (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglês (RU) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglês (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Espanhol (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cirílico)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latim)"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 4faee4b..7bc8581 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda e feedback"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toque aqui para salvar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"inglês (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"inglês (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"espanhol (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Híndi-inglês"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglês (Reino Unido) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglês (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Espanhol (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Híndi-inglês (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirílico)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latino)"</string>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 412ec0e..8af7b2f 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Ajutor și feedback"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Atingeți aici pentru a salva"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicţionar disponibil"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Temă pentru tastatură"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"engleză (Regatul Unit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"engleză (S.U.A.)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"spaniolă (S.U.A.)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engleză (Regatul Unit) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engleză (S.U.A.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spaniolă (S.U.A.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradițională)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Chirilică)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latină)"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index eada313..15843ea 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Нажмите, чтобы сохранить"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Доступен словарь"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавиатуры"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"английский (Великобритания)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"английский (США)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Испанский (США)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Английский (Великобритания, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Английский (США, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испанский (США, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (классическая)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кириллица)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
diff --git a/java/res/values-si-rLK/strings.xml b/java/res/values-si-rLK/strings.xml
index 4829988..7c1ebcb 100644
--- a/java/res/values-si-rLK/strings.xml
+++ b/java/res/values-si-rLK/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"සුරැකීමට මෙතැන ස්පර්ෂ කරන්න"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ශබ්ද කෝෂය ලබාගත හැක"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"යතුරු පුවරු තේමාව"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ඉංග්‍රීසි (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ඉංග්‍රීසි (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ස්පාඤ්ඤ (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"හින්ග්ලිෂ්"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ඉංග්‍රීසි (එ.රා) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ඉංග්‍රීසි (එ.ජ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ස්පාඤ්ඤ (එ.ජ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"හින්ග්ලිෂ් (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (සාම්ප්‍රදායික)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (සිරිලික්)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ලතින්)"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 107f379..02e7c97 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Pomocník a spätná väzba"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Klepnutím tu uložíte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"K dispozícii je slovník"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Motív klávesnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglická klávesnica (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglická klávesnica (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španielčina (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angličtina (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angličtina (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španielčina (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradičná)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrilika)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinka)"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index db24507..2374147 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Pomoč in povratne informacije"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Če želite shraniti, se dotaknite tukaj"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovar je na voljo"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angleščina (Združeno kraljestvo)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angleščina (ZDA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španščina (ZDA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindujska angleščina"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angleščina (VB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angleščina (ZDA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španščina (ZDA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindujska angleščina (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionalna)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirilica)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinica)"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 8cef0d0..c217775 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Додирните овде да бисте сачували"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Речник је доступан"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема тастатуре"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"енглески (УК)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"енглески (САД)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"шпански (САД)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"хенглески"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"енглески (УК) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"енглески (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"шпански (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"хенглески (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционални)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ћирилица)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index c5782cd..30a390b 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Hjälp och feedback"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tryck här om du vill spara"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"En ordlista är tillgänglig"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tangentbordstema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelskt (brittiskt)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelskt (amerikanskt)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"spanska (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi/engelska"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engelska (Storbritannien) <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engelska (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanska (USA (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi/engelska (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionell)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisk)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinsk)"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index f5b8dcb..6060d08 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Gusa hapa ili uhifadhi"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamusi inapatikana"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Maandhari ya kibodi"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Kiingereza cha (Uingereza)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Kiingereza cha (Marekani)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Kihispania (Marekani)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Kiingereza (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Kiingereza (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Kihispania (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cha Jadi)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kikriliki)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kilatini)"</string>
diff --git a/java/res/values-ta-rIN/strings.xml b/java/res/values-ta-rIN/strings.xml
index 606a255..475a1ef 100644
--- a/java/res/values-ta-rIN/strings.xml
+++ b/java/res/values-ta-rIN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"சேமிக்க இங்கு தொடவும்"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"அகராதி உள்ளது"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"விசைப்பலகை தீம்"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ஆங்கிலம் (யூகே)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ஆங்கிலம் (யூஎஸ்)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ஸ்பானிஷ் (யூஎஸ்)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ஹிங்கிலிஷ்"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ஆங்கிலம் (யூகே) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ஆங்கிலம் (யூஎஸ்) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ஸ்பானிஷ் (யூஎஸ்) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ஹிங்கிலிஷ் (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (பாரம்பரியமானது)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (சிரிலிக்)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (இலத்தீன்)"</string>
diff --git a/java/res/values-te-rIN/strings.xml b/java/res/values-te-rIN/strings.xml
index 75152db..2b961c0 100644
--- a/java/res/values-te-rIN/strings.xml
+++ b/java/res/values-te-rIN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"సేవ్ చేయడానికి ఇక్కడ తాకండి"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"నిఘంటువు అందుబాటులో ఉంది"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"కీబోర్డ్ థీమ్"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ఆంగ్లం (యుకె)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ఆంగ్లం (యుఎస్)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"స్పానిష్ (యుఎస్)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"హింగ్లీష్"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ఆంగ్లం (యుకె) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ఆంగ్లం (యుఎస్) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"స్పానిష్ (యుఎస్) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"హింగ్లీష్ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (సాంప్రదాయకం)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (సిరిలిక్)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (లాటిన్)"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index f69c63c..9f4d9b6 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"แตะที่นี่เพื่อบันทึก"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"มีพจนานุกรมให้ใช้งาน"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ชุดรูปแบบแป้นพิมพ์"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"อังกฤษ (สหราชอาณาจักร)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"อังกฤษ (อเมริกัน)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"สเปน (สหรัฐอเมริกา)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ภาษาอังกฤษผสมกับฮินดู"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"อังกฤษ (สหราชอาณาจักร) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"อังกฤษ (สหรัฐอเมริกา) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"สเปน (สหรัฐอเมริกา) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ภาษาอังกฤษผสมกับฮินดู (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ดั้งเดิม)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ซีริลลิก)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ละติน)"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index e22845a..dd9332d 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Tulong at feedback"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Pumindot dito upang mag-save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Available ang diksyunaryo"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema ng keyboard"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Ingles (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Ingles (Estados Unidos)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ingles (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ingles (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillic)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 38ad569..09f5409 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Yardım ve geri bildirim"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Kaydetmek için buraya dokunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sözlük kullanılabilir"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klavye teması"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"İngilizce (BK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"İngilizce (ABD)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"İspanyolca (ABD)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hingilizce"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"İngilizce (İngiltere) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"İngilizce (ABD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"İspanyolca (ABD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hingilizce (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Geleneksel)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kiril)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index f0048ae..762dd22 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Торкніться тут, щоб зберегти"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Словник доступний"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавіатури"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Англійська (Великобританія)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Англійська (США)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"іспанська (США)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хінґліш"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Англійська (Британія) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Англійська (США) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Іспанська (США) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хінґліш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиційна)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кирилиця)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиниця)"</string>
diff --git a/java/res/values-ur-rPK/strings.xml b/java/res/values-ur-rPK/strings.xml
index b1ad5fa..28eebd2 100644
--- a/java/res/values-ur-rPK/strings.xml
+++ b/java/res/values-ur-rPK/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"محفوظ کرنے کیلئے یہاں ٹچ کریں"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"لغت دستیاب ہے"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"کی بورڈ تھیم"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"انگریزی (برطانیہ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"انگریزی (امریکہ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ہسپانوی (امریکہ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ہنگلش"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"انگریزی (برطانیہ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"انگریزی (امریکہ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ہسپانوی (امریکہ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ہنگلش (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (روایتی)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (سیریلک)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (لاطینی)"</string>
diff --git a/java/res/values-uz-rUZ/strings.xml b/java/res/values-uz-rUZ/strings.xml
index 41321e7..eb7d630 100644
--- a/java/res/values-uz-rUZ/strings.xml
+++ b/java/res/values-uz-rUZ/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Yordam va fikr-mulohaza"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Saqlash uchun bu yerga bosing"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Lug‘at mavjud"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatura mavzusi"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Ingliz (Buyuk Britaniya)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Ingliz (AQSH)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Ispan (AQSH)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ingliz (Buyuk Britaniya) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ingliz (AQSH) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Ispan (AQSH) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (an’anaviy)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kirill)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (lotin)"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 30c8d9d..a0057e6 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -80,14 +80,17 @@
     <string name="help_and_feedback" msgid="5328219371839879161">"Trợ giúp và phản hồi"</string>
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Chạm vào đây để lưu"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Có sẵn từ điển"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Chủ đề bàn phím"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Tiếng Anh (Anh)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Tiếng Anh (Mỹ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Tiếng Tây Ban Nha (Mỹ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Tiếng Anh-Hindi"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Tiếng Anh (Anh) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Tiếng Anh (Mỹ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Tiếng Tây Ban Nha (Mỹ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Tiếng Anh-Hindi (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Truyền thống)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tiếng Kirin)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tiếng Latin)"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 0dfb9f9..0986a8e 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"触摸此处即可保存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"有可用字典"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"键盘主题"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英语(英国)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英语(美国)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"西班牙语(美国)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"印地英语"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英式英语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"美式英语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"美式西班牙语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印地英语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(传统)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(西里尔文)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(拉丁文)"</string>
diff --git a/java/res/values-zh-rHK/strings.xml b/java/res/values-zh-rHK/strings.xml
index 791074c..cd744d6 100644
--- a/java/res/values-zh-rHK/strings.xml
+++ b/java/res/values-zh-rHK/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"輕觸即可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英國)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美國)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"西班牙文 (美國)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"印度英文"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英文 (英國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"英文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"西班牙文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印度英文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (傳統)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (西里爾文)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (拉丁文)"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 97a0052..726c697 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"輕觸這裡即可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可用的字典"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英國)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美國)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"西班牙文 (美國)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"印度英文"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英文 (英國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"英文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"西班牙文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印度英文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (傳統)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (斯拉夫文)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (拉丁文)"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 689d501..1ad0f1e 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -80,14 +80,17 @@
     <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="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Thinta lapha ukuze ulondoloze"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Isichazamazwi siyatholakala"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Indikimba yekhibhodi"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"i-English(UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"i-English (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"I-Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"I-Hinglish"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"I-English (UK) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"I-English (US) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Isi-Spanish (US) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"I-Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"Isi-<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradition)"</string>
     <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Isi-Cyrillic)"</string>
     <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Isi-Latin)"</string>
diff --git a/java/res/values/donottranslate-text-decorator.xml b/java/res/values/donottranslate-text-decorator.xml
new file mode 100644
index 0000000..9c39a46
--- /dev/null
+++ b/java/res/values/donottranslate-text-decorator.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <!-- The delay time in milliseconds from to show the commit indicator -->
+    <integer name="text_decorator_delay_in_milliseconds_to_show_commit_indicator">
+        500
+    </integer>
+
+    <!-- The extra margin in dp around the hit area of the commit/add-to-dictionary indicator -->
+    <integer name="text_decorator_hit_area_margin_in_dp">
+        4
+    </integer>
+
+    <!-- If true, the commit/add-to-text indicator will be suppressed when the word isn't going to
+         trigger auto-correction. -->
+    <bool name="text_decorator_only_for_auto_correction">false</bool>
+
+    <!-- If true, the commit/add-to-text indicator will be suppressed when the word is already in
+         the dictionary. -->
+    <bool name="text_decorator_only_for_out_of_vocabulary">false</bool>
+
+    <!-- Background color to be used to highlight the target text when the commit indicator is
+         visible. -->
+    <color name="text_decorator_commit_indicator_text_highlight_color">
+        #B6E2DE
+    </color>
+
+    <!-- Background color of the commit indicator. -->
+    <color name="text_decorator_commit_indicator_background_color">
+        #48B6AC
+    </color>
+
+    <!-- Foreground color of the commit indicator. -->
+    <color name="text_decorator_commit_indicator_foreground_color">
+        #FFFFFF
+    </color>
+
+    <!-- Viewport size of "text_decorator_commit_indicator_path". -->
+    <integer name="text_decorator_commit_indicator_path_size">
+        480
+    </integer>
+
+    <!-- Coordinates of the closed path to be used to render the commit indicator.
+         The format is:  X[0], Y[0], X[1], Y[1], ..., X[N-1], Y[N-1] -->
+    <integer-array name="text_decorator_commit_indicator_path">
+        <item>180</item>
+        <item>323</item>
+        <item>97</item>
+        <item>240</item>
+        <item>68</item>
+        <item>268</item>
+        <item>180</item>
+        <item>380</item>
+        <item>420</item>
+        <item>140</item>
+        <item>392</item>
+        <item>112</item>
+    </integer-array>
+
+    <!-- Background color to be used to highlight the target text when the add-to-dictionary
+         indicator is visible. -->
+    <color name="text_decorator_add_to_dictionary_indicator_text_highlight_color">
+        #D1E7B7
+    </color>
+
+    <!-- Foreground color of the commit indicator. -->
+    <color name="text_decorator_add_to_dictionary_indicator_background_color">
+        #4EB848
+    </color>
+
+    <!-- Foreground color of the add-to-dictionary indicator. -->
+    <color name="text_decorator_add_to_dictionary_indicator_foreground_color">
+        #FFFFFF
+    </color>
+
+    <!-- Viewport size of "text_decorator_add_to_dictionary_indicator_path". -->
+    <integer name="text_decorator_add_to_dictionary_indicator_path_size">
+        480
+    </integer>
+
+    <!-- Coordinates of the closed path to be used to render the add-to-dictionary indicator.
+         The format is: X[0], Y[0], X[1], Y[1], ..., X[N-1], Y[N-1] -->
+    <integer-array name="text_decorator_add_to_dictionary_indicator_path">
+        <item>380</item>
+        <item>260</item>
+        <item>260</item>
+        <item>260</item>
+        <item>260</item>
+        <item>380</item>
+        <item>220</item>
+        <item>380</item>
+        <item>220</item>
+        <item>260</item>
+        <item>100</item>
+        <item>260</item>
+        <item>100</item>
+        <item>220</item>
+        <item>220</item>
+        <item>220</item>
+        <item>220</item>
+        <item>100</item>
+        <item>260</item>
+        <item>100</item>
+        <item>260</item>
+        <item>220</item>
+        <item>380</item>
+        <item>220</item>
+    </integer-array>
+</resources>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 1d9dedb..30bd1df 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -360,7 +360,7 @@
                 R.layout.input_view, null);
         mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame);
         mEmojiPalettesView = (EmojiPalettesView)mCurrentInputView.findViewById(
-                R.id.emoji_keyboard_view);
+                R.id.emoji_palettes_view);
 
         mKeyboardView = (MainKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
         mKeyboardView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled);
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
new file mode 100644
index 0000000..1785161
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.inputmethodservice.InputMethodService;
+import android.os.Message;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.CursorAnchorInfo;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A controller class of commit/add-to-dictionary indicator (a.k.a. TextDecorator). This class
+ * is designed to be independent of UI subsystems such as {@link View}. All the UI related
+ * operations are delegated to {@link TextDecoratorUi} via {@link TextDecoratorUiOperator}.
+ */
+public class TextDecorator {
+    private static final String TAG = TextDecorator.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    private static final int MODE_NONE = 0;
+    private static final int MODE_COMMIT = 1;
+    private static final int MODE_ADD_TO_DICTIONARY = 2;
+
+    private int mMode = MODE_NONE;
+
+    private final PointF mLocalOrigin = new PointF();
+    private final RectF mRelativeIndicatorBounds = new RectF();
+    private final RectF mRelativeComposingTextBounds = new RectF();
+
+    private boolean mIsFullScreenMode = false;
+    private SuggestedWordInfo mWaitingWord = null;
+    private CursorAnchorInfoCompatWrapper mCursorAnchorInfoWrapper = null;
+
+    @Nonnull
+    private final Listener mListener;
+
+    @Nonnull
+    private TextDecoratorUiOperator mUiOperator = EMPTY_UI_OPERATOR;
+
+    public interface Listener {
+        /**
+         * Called when the user clicks the composing text to commit.
+         * @param wordInfo the suggested word which the user clicked on.
+         */
+        void onClickComposingTextToCommit(final SuggestedWordInfo wordInfo);
+
+        /**
+         * Called when the user clicks the composing text to add the word into the dictionary.
+         * @param wordInfo the suggested word which the user clicked on.
+         */
+        void onClickComposingTextToAddToDictionary(final SuggestedWordInfo wordInfo);
+    }
+
+    public TextDecorator(final Listener listener) {
+        mListener = (listener != null) ? listener : EMPTY_LISTENER;
+    }
+
+    /**
+     * Sets the UI operator for {@link TextDecorator}. Any user visible operations will be
+     * delegated to the associated UI operator.
+     * @param uiOperator the UI operator to be associated.
+     */
+    public void setUiOperator(final TextDecoratorUiOperator uiOperator) {
+        mUiOperator.disposeUi();
+        mUiOperator = uiOperator;
+        mUiOperator.setOnClickListener(getOnClickHandler());
+    }
+
+    private final Runnable mDefaultOnClickHandler = new Runnable() {
+        @Override
+        public void run() {
+            onClickIndicator();
+        }
+    };
+
+    @UsedForTesting
+    final Runnable getOnClickHandler() {
+        return mDefaultOnClickHandler;
+    }
+
+    /**
+     * Shows the "Commit" indicator and associates it with the given suggested word.
+     *
+     * <p>The effect of {@link #showCommitIndicator(SuggestedWordInfo)} and
+     * {@link #showAddToDictionaryIndicator(SuggestedWordInfo)} are exclusive to each other. Call
+     * {@link #reset()} to hide the indicator.</p>
+     *
+     * @param wordInfo the suggested word which should be associated with the indicator. This object
+     * will be passed back in {@link Listener#onClickComposingTextToCommit(SuggestedWordInfo)}
+     */
+    public void showCommitIndicator(final SuggestedWordInfo wordInfo) {
+        if (mMode == MODE_COMMIT && wordInfo != null &&
+                TextUtils.equals(mWaitingWord.mWord, wordInfo.mWord)) {
+            // Skip layout for better performance.
+            return;
+        }
+        mWaitingWord = wordInfo;
+        mMode = MODE_COMMIT;
+        layoutLater();
+    }
+
+    /**
+     * Shows the "Add to dictionary" indicator and associates it with associating the given
+     * suggested word.
+     *
+     * <p>The effect of {@link #showCommitIndicator(SuggestedWordInfo)} and
+     * {@link #showAddToDictionaryIndicator(SuggestedWordInfo)} are exclusive to each other. Call
+     * {@link #reset()} to hide the indicator.</p>
+     *
+     * @param wordInfo the suggested word which should be associated with the indicator. This object
+     * will be passed back in
+     * {@link Listener#onClickComposingTextToAddToDictionary(SuggestedWordInfo)}.
+     */
+    public void showAddToDictionaryIndicator(final SuggestedWordInfo wordInfo) {
+        if (mMode == MODE_ADD_TO_DICTIONARY && wordInfo != null &&
+                TextUtils.equals(mWaitingWord.mWord, wordInfo.mWord)) {
+            // Skip layout for better performance.
+            return;
+        }
+        mWaitingWord = wordInfo;
+        mMode = MODE_ADD_TO_DICTIONARY;
+        layoutLater();
+        return;
+    }
+
+    /**
+     * Must be called when the input method is about changing to for from the full screen mode.
+     * @param fullScreenMode {@code true} if the input method is entering the full screen mode.
+     * {@code false} is the input method is finishing the full screen mode.
+     */
+    public void notifyFullScreenMode(final boolean fullScreenMode) {
+        final boolean currentFullScreenMode = mIsFullScreenMode;
+        if (!currentFullScreenMode && fullScreenMode) {
+            // Currently full screen mode is not supported.
+            // TODO: Support full screen mode.
+            mUiOperator.hideUi();
+        }
+        mIsFullScreenMode = fullScreenMode;
+    }
+
+    /**
+     * Resets previous requests and makes indicator invisible.
+     */
+    public void reset() {
+        mWaitingWord = null;
+        mMode = MODE_NONE;
+        mLocalOrigin.set(0.0f, 0.0f);
+        mRelativeIndicatorBounds.set(0.0f, 0.0f, 0.0f, 0.0f);
+        mRelativeComposingTextBounds.set(0.0f, 0.0f, 0.0f, 0.0f);
+        cancelLayoutInternalExpectedly("Resetting internal state.");
+    }
+
+    /**
+     * Must be called when the {@link InputMethodService#onUpdateCursorAnchorInfo()} is called.
+     *
+     * <p>CAVEAT: Currently the input method author is responsible for ignoring
+     * {@link InputMethodService#onUpdateCursorAnchorInfo()} called in full screen mode.</p>
+     * @param info the compatibility wrapper object for the received {@link CursorAnchorInfo}.
+     */
+    public void onUpdateCursorAnchorInfo(final CursorAnchorInfoCompatWrapper info) {
+        if (mIsFullScreenMode) {
+            // TODO: Consider to call InputConnection#requestCursorAnchorInfo to disable the
+            // event callback to suppress unnecessary event callbacks.
+            return;
+        }
+        mCursorAnchorInfoWrapper = info;
+        // Do not use layoutLater() to minimize the latency.
+        layoutImmediately();
+    }
+
+    /**
+     * Hides indicator if the new composing text doesn't match the expected one.
+     *
+     * <p>Calling this method is optional but recommended whenever the new composition is passed to
+     * the application. The motivation of this method is to reduce the UI latency. With this method,
+     * we can hide the indicator without waiting the arrival of the
+     * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} callback, assuming that
+     * the application accepts the new composing text without any modification. Even if this
+     * assumption is false, the indicator will be shown again when
+     * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is actually received.
+     * </p>
+     *
+     * @param newComposingText the new composing text that is being passed to the application.
+     */
+    public void hideIndicatorIfNecessary(final CharSequence newComposingText) {
+        if (mMode != MODE_COMMIT && mMode != MODE_ADD_TO_DICTIONARY) {
+            return;
+        }
+        if (!TextUtils.equals(newComposingText, mWaitingWord.mWord)) {
+            mUiOperator.hideUi();
+        }
+    }
+
+    private void cancelLayoutInternalUnexpectedly(final String message) {
+        mUiOperator.hideUi();
+        Log.d(TAG, message);
+    }
+
+    private void cancelLayoutInternalExpectedly(final String message) {
+        mUiOperator.hideUi();
+        if (DEBUG) {
+            Log.d(TAG, message);
+        }
+    }
+
+    private void layoutLater() {
+        mLayoutInvalidator.invalidateLayout();
+    }
+
+
+    private void layoutImmediately() {
+        // Clear pending layout requests.
+        mLayoutInvalidator.cancelInvalidateLayout();
+        layoutMain();
+    }
+
+    private void layoutMain() {
+        if (mIsFullScreenMode) {
+            cancelLayoutInternalUnexpectedly("Full screen mode isn't yet supported.");
+            return;
+        }
+
+        if (mMode != MODE_COMMIT && mMode != MODE_ADD_TO_DICTIONARY) {
+            if (mMode == MODE_NONE) {
+                cancelLayoutInternalExpectedly("Not ready for layouting.");
+            } else {
+                cancelLayoutInternalUnexpectedly("Unknown mMode=" + mMode);
+            }
+            return;
+        }
+
+        final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
+
+        if (info == null) {
+            cancelLayoutInternalExpectedly("CursorAnchorInfo isn't available.");
+            return;
+        }
+
+        final Matrix matrix = info.getMatrix();
+        if (matrix == null) {
+            cancelLayoutInternalUnexpectedly("Matrix is null");
+        }
+
+        final CharSequence composingText = info.getComposingText();
+        if (mMode == MODE_COMMIT) {
+            if (composingText == null) {
+                cancelLayoutInternalExpectedly("composingText is null.");
+                return;
+            }
+            final int composingTextStart = info.getComposingTextStart();
+            final int lastCharRectIndex = composingTextStart + composingText.length() - 1;
+            final RectF lastCharRect = info.getCharacterRect(lastCharRectIndex);
+            final int lastCharRectFlag = info.getCharacterRectFlags(lastCharRectIndex);
+            final int lastCharRectType =
+                    lastCharRectFlag & CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_MASK;
+            if (lastCharRect == null || matrix == null || lastCharRectType !=
+                    CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_FULLY_VISIBLE) {
+                mUiOperator.hideUi();
+                return;
+            }
+            final RectF segmentStartCharRect = new RectF(lastCharRect);
+            for (int i = composingText.length() - 2; i >= 0; --i) {
+                final RectF charRect = info.getCharacterRect(composingTextStart + i);
+                if (charRect == null) {
+                    break;
+                }
+                if (charRect.top != segmentStartCharRect.top) {
+                    break;
+                }
+                if (charRect.bottom != segmentStartCharRect.bottom) {
+                    break;
+                }
+                segmentStartCharRect.set(charRect);
+            }
+
+            mLocalOrigin.set(lastCharRect.right, lastCharRect.top);
+            mRelativeIndicatorBounds.set(lastCharRect.right, lastCharRect.top,
+                    lastCharRect.right + lastCharRect.height(), lastCharRect.bottom);
+            mRelativeIndicatorBounds.offset(-mLocalOrigin.x, -mLocalOrigin.y);
+
+            mRelativeIndicatorBounds.set(lastCharRect.right, lastCharRect.top,
+                    lastCharRect.right + lastCharRect.height(), lastCharRect.bottom);
+            mRelativeIndicatorBounds.offset(-mLocalOrigin.x, -mLocalOrigin.y);
+
+            mRelativeComposingTextBounds.set(segmentStartCharRect.left, segmentStartCharRect.top,
+                    segmentStartCharRect.right, segmentStartCharRect.bottom);
+            mRelativeComposingTextBounds.offset(-mLocalOrigin.x, -mLocalOrigin.y);
+
+            if (mWaitingWord == null) {
+                cancelLayoutInternalExpectedly("mWaitingText is null.");
+                return;
+            }
+            if (TextUtils.isEmpty(mWaitingWord.mWord)) {
+                cancelLayoutInternalExpectedly("mWaitingText.mWord is empty.");
+                return;
+            }
+            if (!TextUtils.equals(composingText, mWaitingWord.mWord)) {
+                // This is indeed an expected situation because of the asynchronous nature of
+                // input method framework in Android. Note that composingText is notified from the
+                // application, while mWaitingWord.mWord is obtained directly from the InputLogic.
+                cancelLayoutInternalExpectedly(
+                        "Composing text doesn't match the one we are waiting for.");
+                return;
+            }
+        } else {
+            if (!TextUtils.isEmpty(composingText)) {
+                // This is an unexpected case.
+                // TODO: Document this.
+                mUiOperator.hideUi();
+                return;
+            }
+            // In MODE_ADD_TO_DICTIONARY, we cannot retrieve the character position at all because
+            // of the lack of composing text. We will use the insertion marker position instead.
+            if (info.isInsertionMarkerClipped()) {
+                mUiOperator.hideUi();
+                return;
+            }
+            final float insertionMarkerHolizontal = info.getInsertionMarkerHorizontal();
+            final float insertionMarkerTop = info.getInsertionMarkerTop();
+            mLocalOrigin.set(insertionMarkerHolizontal, insertionMarkerTop);
+        }
+
+        final RectF indicatorBounds = new RectF(mRelativeIndicatorBounds);
+        final RectF composingTextBounds = new RectF(mRelativeComposingTextBounds);
+        indicatorBounds.offset(mLocalOrigin.x, mLocalOrigin.y);
+        composingTextBounds.offset(mLocalOrigin.x, mLocalOrigin.y);
+        mUiOperator.layoutUi(mMode == MODE_COMMIT, matrix, indicatorBounds, composingTextBounds);
+    }
+
+    private void onClickIndicator() {
+        if (mWaitingWord == null || TextUtils.isEmpty(mWaitingWord.mWord)) {
+            return;
+        }
+        switch (mMode) {
+            case MODE_COMMIT:
+                mListener.onClickComposingTextToCommit(mWaitingWord);
+                break;
+            case MODE_ADD_TO_DICTIONARY:
+                mListener.onClickComposingTextToAddToDictionary(mWaitingWord);
+                break;
+        }
+    }
+
+    private final LayoutInvalidator mLayoutInvalidator = new LayoutInvalidator(this);
+
+    /**
+     * Used for managing pending layout tasks for {@link TextDecorator#layoutLater()}.
+     */
+    private static final class LayoutInvalidator {
+        private final HandlerImpl mHandler;
+        public LayoutInvalidator(final TextDecorator ownerInstance) {
+            mHandler = new HandlerImpl(ownerInstance);
+        }
+
+        private static final int MSG_LAYOUT = 0;
+
+        private static final class HandlerImpl
+                extends LeakGuardHandlerWrapper<TextDecorator> {
+            public HandlerImpl(final TextDecorator ownerInstance) {
+                super(ownerInstance);
+            }
+
+            @Override
+            public void handleMessage(final Message msg) {
+                final TextDecorator owner = getOwnerInstance();
+                if (owner == null) {
+                    return;
+                }
+                switch (msg.what) {
+                    case MSG_LAYOUT:
+                        owner.layoutMain();
+                        break;
+                }
+            }
+        }
+
+        /**
+         * Puts a layout task into the scheduler. Does nothing if one or more layout tasks are
+         * already scheduled.
+         */
+        public void invalidateLayout() {
+            if (!mHandler.hasMessages(MSG_LAYOUT)) {
+                mHandler.obtainMessage(MSG_LAYOUT).sendToTarget();
+            }
+        }
+
+        /**
+         * Clears the pending layout tasks.
+         */
+        public void cancelInvalidateLayout() {
+            mHandler.removeMessages(MSG_LAYOUT);
+        }
+    }
+
+    private final static Listener EMPTY_LISTENER = new Listener() {
+        @Override
+        public void onClickComposingTextToCommit(SuggestedWordInfo wordInfo) {
+        }
+        @Override
+        public void onClickComposingTextToAddToDictionary(SuggestedWordInfo wordInfo) {
+        }
+    };
+
+    private final static TextDecoratorUiOperator EMPTY_UI_OPERATOR = new TextDecoratorUiOperator() {
+        @Override
+        public void disposeUi() {
+        }
+        @Override
+        public void hideUi() {
+        }
+        @Override
+        public void setOnClickListener(Runnable listener) {
+        }
+        @Override
+        public void layoutUi(boolean isCommitMode, Matrix matrix, RectF indicatorBounds,
+                RectF composingTextBounds) {
+        }
+    };
+}
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java b/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java
new file mode 100644
index 0000000..6e215a9
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.graphics.drawable.ColorDrawable;
+import android.inputmethodservice.InputMethodService;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewParent;
+import android.widget.PopupWindow;
+import android.widget.RelativeLayout;
+
+import com.android.inputmethod.latin.R;
+
+/**
+ * Used as the UI component of {@link TextDecorator}.
+ */
+public final class TextDecoratorUi implements TextDecoratorUiOperator {
+    private static final boolean VISUAL_DEBUG = false;
+    private static final int VISUAL_DEBUG_HIT_AREA_COLOR = 0x80ff8000;
+
+    private final RelativeLayout mLocalRootView;
+    private final CommitIndicatorView mCommitIndicatorView;
+    private final AddToDictionaryIndicatorView mAddToDictionaryIndicatorView;
+    private final PopupWindow mTouchEventWindow;
+    private final View mTouchEventWindowClickListenerView;
+    private final float mHitAreaMarginInPixels;
+
+    /**
+     * This constructor is designed to be called from {@link InputMethodService#setInputView(View)}.
+     * Other usages are not supported.
+     *
+     * @param context the context of the input method.
+     * @param inputView the view that is passed to {@link InputMethodService#setInputView(View)}.
+     */
+    public TextDecoratorUi(final Context context, final View inputView) {
+        final Resources resources = context.getResources();
+        final int hitAreaMarginInDP = resources.getInteger(
+                R.integer.text_decorator_hit_area_margin_in_dp);
+        mHitAreaMarginInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                hitAreaMarginInDP, resources.getDisplayMetrics());
+
+        mLocalRootView = new RelativeLayout(context);
+        mLocalRootView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
+        // TODO: Use #setBackground(null) for API Level >= 16.
+        mLocalRootView.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+
+        final ViewGroup contentView = getContentView(inputView);
+        mCommitIndicatorView = new CommitIndicatorView(context);
+        mAddToDictionaryIndicatorView = new AddToDictionaryIndicatorView(context);
+        mLocalRootView.addView(mCommitIndicatorView);
+        mLocalRootView.addView(mAddToDictionaryIndicatorView);
+        if (contentView != null) {
+            contentView.addView(mLocalRootView);
+        }
+
+        // This popup window is used to avoid the limitation that the input method is not able to
+        // observe the touch events happening outside of InputMethodService.Insets#touchableRegion.
+        // We don't use this popup window for rendering the UI for performance reasons though.
+        mTouchEventWindow = new PopupWindow(context);
+        if (VISUAL_DEBUG) {
+            mTouchEventWindow.setBackgroundDrawable(new ColorDrawable(VISUAL_DEBUG_HIT_AREA_COLOR));
+        } else {
+            mTouchEventWindow.setBackgroundDrawable(null);
+        }
+        mTouchEventWindowClickListenerView = new View(context);
+        mTouchEventWindow.setContentView(mTouchEventWindowClickListenerView);
+    }
+
+    @Override
+    public void disposeUi() {
+        if (mLocalRootView != null) {
+            final ViewParent parent = mLocalRootView.getParent();
+            if (parent != null && parent instanceof ViewGroup) {
+                ((ViewGroup) parent).removeView(mLocalRootView);
+            }
+            mLocalRootView.removeAllViews();
+        }
+        if (mTouchEventWindow != null) {
+            mTouchEventWindow.dismiss();
+        }
+    }
+
+    @Override
+    public void hideUi() {
+        mCommitIndicatorView.setVisibility(View.GONE);
+        mAddToDictionaryIndicatorView.setVisibility(View.GONE);
+        mTouchEventWindow.dismiss();
+    }
+
+    @Override
+    public void layoutUi(final boolean isCommitMode, final Matrix matrix,
+            final RectF indicatorBounds, final RectF composingTextBounds) {
+        final RectF indicatorBoundsInScreenCoordinates = new RectF();
+        matrix.mapRect(indicatorBoundsInScreenCoordinates, indicatorBounds);
+        mCommitIndicatorView.setBounds(indicatorBoundsInScreenCoordinates);
+        mAddToDictionaryIndicatorView.setBounds(indicatorBoundsInScreenCoordinates);
+
+        final RectF hitAreaBounds = new RectF(composingTextBounds);
+        hitAreaBounds.union(indicatorBounds);
+        final RectF hitAreaBoundsInScreenCoordinates = new RectF();
+        matrix.mapRect(hitAreaBoundsInScreenCoordinates, hitAreaBounds);
+        hitAreaBoundsInScreenCoordinates.inset(-mHitAreaMarginInPixels, -mHitAreaMarginInPixels);
+
+        final int[] originScreen = new int[2];
+        mLocalRootView.getLocationOnScreen(originScreen);
+        final int viewOriginX = originScreen[0];
+        final int viewOriginY = originScreen[1];
+
+        final View toBeShown;
+        final View toBeHidden;
+        if (isCommitMode) {
+            toBeShown = mCommitIndicatorView;
+            toBeHidden = mAddToDictionaryIndicatorView;
+        } else {
+            toBeShown = mAddToDictionaryIndicatorView;
+            toBeHidden = mCommitIndicatorView;
+        }
+        toBeShown.setX(indicatorBoundsInScreenCoordinates.left - viewOriginX);
+        toBeShown.setY(indicatorBoundsInScreenCoordinates.top - viewOriginY);
+        toBeShown.setVisibility(View.VISIBLE);
+        toBeHidden.setVisibility(View.GONE);
+
+        if (mTouchEventWindow.isShowing()) {
+            mTouchEventWindow.update((int)hitAreaBoundsInScreenCoordinates.left - viewOriginX,
+                    (int)hitAreaBoundsInScreenCoordinates.top - viewOriginY,
+                    (int)hitAreaBoundsInScreenCoordinates.width(),
+                    (int)hitAreaBoundsInScreenCoordinates.height());
+        } else {
+            mTouchEventWindow.setWidth((int)hitAreaBoundsInScreenCoordinates.width());
+            mTouchEventWindow.setHeight((int)hitAreaBoundsInScreenCoordinates.height());
+            mTouchEventWindow.showAtLocation(mLocalRootView, Gravity.NO_GRAVITY,
+                    (int)hitAreaBoundsInScreenCoordinates.left - viewOriginX,
+                    (int)hitAreaBoundsInScreenCoordinates.top - viewOriginY);
+        }
+    }
+
+    @Override
+    public void setOnClickListener(final Runnable listener) {
+        mTouchEventWindowClickListenerView.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View arg0) {
+                listener.run();
+            }
+        });
+    }
+
+    private static class IndicatorView extends View {
+        private final Path mPath;
+        private final Path mTmpPath = new Path();
+        private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        private final Matrix mMatrix = new Matrix();
+        private final int mBackgroundColor;
+        private final int mForegroundColor;
+        private final RectF mBounds = new RectF();
+        public IndicatorView(Context context, final int pathResourceId,
+                final int sizeResourceId, final int backgroundColorResourceId,
+                final int foregroundColroResourceId) {
+            super(context);
+            final Resources resources = context.getResources();
+            mPath = createPath(resources, pathResourceId, sizeResourceId);
+            mBackgroundColor = resources.getColor(backgroundColorResourceId);
+            mForegroundColor = resources.getColor(foregroundColroResourceId);
+        }
+
+        public void setBounds(final RectF rect) {
+            mBounds.set(rect);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            mPaint.setColor(mBackgroundColor);
+            mPaint.setStyle(Paint.Style.FILL);
+            canvas.drawRect(0.0f, 0.0f, mBounds.width(), mBounds.height(), mPaint);
+
+            mMatrix.reset();
+            mMatrix.postScale(mBounds.width(), mBounds.height());
+            mPath.transform(mMatrix, mTmpPath);
+            mPaint.setColor(mForegroundColor);
+            canvas.drawPath(mTmpPath, mPaint);
+        }
+
+        private static Path createPath(final Resources resources, final int pathResourceId,
+                final int sizeResourceId) {
+            final int size = resources.getInteger(sizeResourceId);
+            final float normalizationFactor = 1.0f / size;
+            final int[] array = resources.getIntArray(pathResourceId);
+
+            final Path path = new Path();
+            for (int i = 0; i < array.length; i += 2) {
+                if (i == 0) {
+                    path.moveTo(array[i] * normalizationFactor, array[i + 1] * normalizationFactor);
+                } else {
+                    path.lineTo(array[i] * normalizationFactor, array[i + 1] * normalizationFactor);
+                }
+            }
+            path.close();
+            return path;
+        }
+    }
+
+    private static ViewGroup getContentView(final View view) {
+        final View rootView = view.getRootView();
+        if (rootView == null) {
+            return null;
+        }
+
+        final ViewGroup windowContentView = (ViewGroup)rootView.findViewById(android.R.id.content);
+        if (windowContentView == null) {
+            return null;
+        }
+        return windowContentView;
+    }
+
+    private static final class CommitIndicatorView extends TextDecoratorUi.IndicatorView {
+        public CommitIndicatorView(final Context context) {
+            super(context, R.array.text_decorator_commit_indicator_path,
+                    R.integer.text_decorator_commit_indicator_path_size,
+                    R.color.text_decorator_commit_indicator_background_color,
+                    R.color.text_decorator_commit_indicator_foreground_color);
+        }
+    }
+
+    private static final class AddToDictionaryIndicatorView extends TextDecoratorUi.IndicatorView {
+        public AddToDictionaryIndicatorView(final Context context) {
+            super(context, R.array.text_decorator_add_to_dictionary_indicator_path,
+                    R.integer.text_decorator_add_to_dictionary_indicator_path_size,
+                    R.color.text_decorator_add_to_dictionary_indicator_background_color,
+                    R.color.text_decorator_add_to_dictionary_indicator_foreground_color);
+        }
+    }
+}
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java b/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java
new file mode 100644
index 0000000..f84e12d
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.graphics.RectF;
+
+/**
+ * This interface defines how UI operations required for {@link TextDecorator} are delegated to
+ * the actual UI implementation class.
+ */
+public interface TextDecoratorUiOperator {
+    /**
+     * Called to notify that the UI is ready to be disposed.
+     */
+    void disposeUi();
+
+    /**
+     * Called when the UI should become invisible.
+     */
+    void hideUi();
+
+    /**
+     * Called to set the new click handler.
+     * @param onClickListener the callback object whose {@link Runnable#run()} should be called when
+     * the indicator is clicked.
+     */
+    void setOnClickListener(final Runnable onClickListener);
+
+    /**
+     * Called when the layout should be updated.
+     * @param isCommitMode {@code true} if the commit indicator should be shown. Show the
+     * add-to-dictionary indicator otherwise.
+     * @param matrix The matrix that transforms the local coordinates into the screen coordinates.
+     * @param indicatorBounds The bounding box of the indicator, in local coordinates.
+     * @param composingTextBounds The bounding box of the composing text, in local coordinates.
+     */
+    void layoutUi(final boolean isCommitMode, final Matrix matrix, final RectF indicatorBounds,
+            final RectF composingTextBounds);
+}
diff --git a/java/src/com/android/inputmethod/latin/InputView.java b/java/src/com/android/inputmethod/latin/InputView.java
index e9e12f0..7fa9354 100644
--- a/java/src/com/android/inputmethod/latin/InputView.java
+++ b/java/src/com/android/inputmethod/latin/InputView.java
@@ -21,14 +21,14 @@
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
-import android.widget.LinearLayout;
+import android.widget.FrameLayout;
 
 import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.keyboard.MainKeyboardView;
 import com.android.inputmethod.latin.suggestions.MoreSuggestionsView;
 import com.android.inputmethod.latin.suggestions.SuggestionStripView;
 
-public final class InputView extends LinearLayout {
+public final class InputView extends FrameLayout {
     private final Rect mInputViewRect = new Rect();
     private MainKeyboardView mMainKeyboardView;
     private KeyboardTopPaddingForwarder mKeyboardTopPaddingForwarder;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 9a3927c..ee0ff5c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -29,7 +29,6 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
@@ -43,6 +42,7 @@
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.SparseArray;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
@@ -57,7 +57,6 @@
 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;
 import com.android.inputmethod.event.Event;
@@ -69,6 +68,7 @@
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.keyboard.MainKeyboardView;
+import com.android.inputmethod.keyboard.TextDecoratorUi;
 import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.define.DebugFlags;
@@ -94,6 +94,7 @@
 import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
 import com.android.inputmethod.latin.utils.StatsUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+import com.android.inputmethod.latin.utils.ViewLayoutUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -150,8 +151,6 @@
 
     // TODO: Move these {@link View}s to {@link KeyboardSwitcher}.
     private View mInputView;
-    private View mExtractArea;
-    private View mKeyPreviewBackingView;
     private SuggestionStripView mSuggestionStripView;
 
     private RichInputMethodManager mRichImm;
@@ -183,8 +182,9 @@
         private static final int MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED = 6;
         private static final int MSG_RESET_CACHES = 7;
         private static final int MSG_WAIT_FOR_DICTIONARY_LOAD = 8;
+        private static final int MSG_SHOW_COMMIT_INDICATOR = 9;
         // Update this when adding new messages
-        private static final int MSG_LAST = MSG_WAIT_FOR_DICTIONARY_LOAD;
+        private static final int MSG_LAST = MSG_SHOW_COMMIT_INDICATOR;
 
         private static final int ARG1_NOT_GESTURE_INPUT = 0;
         private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
@@ -195,6 +195,7 @@
 
         private int mDelayInMillisecondsToUpdateSuggestions;
         private int mDelayInMillisecondsToUpdateShiftState;
+        private int mDelayInMillisecondsToShowCommitIndicator;
 
         public UIHandler(final LatinIME ownerInstance) {
             super(ownerInstance);
@@ -206,10 +207,12 @@
                 return;
             }
             final Resources res = latinIme.getResources();
-            mDelayInMillisecondsToUpdateSuggestions =
-                    res.getInteger(R.integer.config_delay_in_milliseconds_to_update_suggestions);
-            mDelayInMillisecondsToUpdateShiftState =
-                    res.getInteger(R.integer.config_delay_in_milliseconds_to_update_shift_state);
+            mDelayInMillisecondsToUpdateSuggestions = res.getInteger(
+                    R.integer.config_delay_in_milliseconds_to_update_suggestions);
+            mDelayInMillisecondsToUpdateShiftState = res.getInteger(
+                    R.integer.config_delay_in_milliseconds_to_update_shift_state);
+            mDelayInMillisecondsToShowCommitIndicator = res.getInteger(
+                    R.integer.text_decorator_delay_in_milliseconds_to_show_commit_indicator);
         }
 
         @Override
@@ -258,7 +261,7 @@
             case MSG_RESET_CACHES:
                 final SettingsValues settingsValues = latinIme.mSettings.getCurrent();
                 if (latinIme.mInputLogic.retryResetCachesAndReturnSuccess(
-                        msg.arg1 == 1 /* tryResumeSuggestions */,
+                        msg.arg1 == ARG1_TRUE /* tryResumeSuggestions */,
                         msg.arg2 /* remainingTries */, this /* handler */)) {
                     // If we were able to reset the caches, then we can reload the keyboard.
                     // Otherwise, we'll do it when we can.
@@ -267,6 +270,14 @@
                             latinIme.getCurrentRecapitalizeState());
                 }
                 break;
+            case MSG_SHOW_COMMIT_INDICATOR:
+                // Protocol of MSG_SET_COMMIT_INDICATOR_ENABLED:
+                // - what: MSG_SHOW_COMMIT_INDICATOR
+                // - arg1: not used.
+                // - arg2: not used.
+                // - obj:  the Runnable object to be called back.
+                ((Runnable) msg.obj).run();
+                break;
             case MSG_WAIT_FOR_DICTIONARY_LOAD:
                 Log.i(TAG, "Timeout waiting for dictionary load");
                 break;
@@ -367,6 +378,19 @@
             obtainMessage(MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED, suggestedWords).sendToTarget();
         }
 
+        /**
+         * Posts a delayed task to show the commit indicator.
+         *
+         * <p>Only one task can exist in the queue. When this method is called, any prior task that
+         * has not yet fired will be canceled.</p>
+         * @param task the runnable object that will be fired when the delayed task is dispatched.
+         */
+        public void postShowCommitIndicatorTask(final Runnable task) {
+            removeMessages(MSG_SHOW_COMMIT_INDICATOR);
+            sendMessageDelayed(obtainMessage(MSG_SHOW_COMMIT_INDICATOR, task),
+                    mDelayInMillisecondsToShowCommitIndicator);
+        }
+
         // Working variables for the following methods.
         private boolean mIsOrientationChanging;
         private boolean mPendingSuccessiveImsCallback;
@@ -710,13 +734,11 @@
     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);
         mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view);
         if (hasSuggestionStripView()) {
             mSuggestionStripView.setListener(this, view);
         }
+        mInputLogic.setTextDecoratorUi(new TextDecoratorUi(this, view));
     }
 
     @Override
@@ -751,20 +773,13 @@
         // is not guaranteed. It may even be called at the same time on a different thread.
         final RichInputMethodSubtype richSubtype = new RichInputMethodSubtype(subtype);
         mSubtypeSwitcher.onSubtypeChanged(richSubtype);
-        mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype));
+        mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype),
+                mSettings.getCurrent());
         loadKeyboard();
     }
 
     private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
         super.onStartInput(editorInfo, restarting);
-        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
-            // AcceptTypedWord feature relies on CursorAnchorInfo.
-            if (mSettings.getCurrent().mShouldShowUiToAcceptTypedWord) {
-                InputConnectionCompatUtils.requestUpdateCursorAnchorInfo(
-                        getCurrentInputConnection(), true /* enableMonitor */,
-                        true /* requestImmediateCallback */);
-            }
-        }
     }
 
     @SuppressWarnings("deprecation")
@@ -833,7 +848,8 @@
         // span, so we should reset our state unconditionally, even if restarting is true.
         // We also tell the input logic about the combining rules for the current subtype, so
         // it can adjust its combiners if needed.
-        mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype());
+        mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype(),
+                currentSettingsValues);
 
         // Note: the following does a round-trip IPC on the main thread: be careful
         final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
@@ -973,9 +989,7 @@
     // @Override
     public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) {
         if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
-            final CursorAnchorInfoCompatWrapper wrapper =
-                    CursorAnchorInfoCompatWrapper.fromObject(info);
-            // TODO: Implement here
+            mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
         }
     }
 
@@ -1058,36 +1072,6 @@
         setSuggestedWords(suggestedWords);
     }
 
-    private int getAdjustedBackingViewHeight() {
-        final int currentHeight = mKeyPreviewBackingView.getHeight();
-        if (currentHeight > 0) {
-            return currentHeight;
-        }
-
-        final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView();
-        if (visibleKeyboardView == null) {
-            return 0;
-        }
-        // TODO: !!!!!!!!!!!!!!!!!!!! Handle different backing view heights between the main   !!!
-        // keyboard and the emoji keyboard. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-        final int keyboardHeight = visibleKeyboardView.getHeight();
-        final int suggestionsHeight = mSuggestionStripView.getHeight();
-        final int displayHeight = getResources().getDisplayMetrics().heightPixels;
-        final Rect rect = new Rect();
-        mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect);
-        final int notificationBarHeight = rect.top;
-        final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight
-                - keyboardHeight;
-
-        final LayoutParams params = mKeyPreviewBackingView.getLayoutParams();
-        mSuggestionStripView.setMoreSuggestionsHeight(remainingHeight);
-
-        // Let the backing cover the remaining region entirely.
-        params.height = remainingHeight;
-        mKeyPreviewBackingView.setLayoutParams(params);
-        return params.height;
-    }
-
     @Override
     public void onComputeInsets(final InputMethodService.Insets outInsets) {
         super.onComputeInsets(outInsets);
@@ -1095,40 +1079,30 @@
         if (visibleKeyboardView == null || !hasSuggestionStripView()) {
             return;
         }
+        final int inputHeight = mInputView.getHeight();
         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();
+            outInsets.touchableInsets = inputHeight;
+            outInsets.visibleTopInsets = inputHeight;
             return;
         }
-        final int adjustedBackingHeight = getAdjustedBackingViewHeight();
-        final boolean backingGone = (mKeyPreviewBackingView.getVisibility() == View.GONE);
-        final int backingHeight = backingGone ? 0 : adjustedBackingHeight;
-        // In fullscreen mode, the height of the extract area managed by InputMethodService should
-        // be considered.
-        // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}.
-        final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0;
-        final int suggestionsHeight = (mSuggestionStripView.getVisibility() == View.GONE) ? 0
-                : mSuggestionStripView.getHeight();
-        final int extraHeight = extractHeight + backingHeight + suggestionsHeight;
-        int visibleTopY = extraHeight;
-        // Need to set touchable region only if input view is being shown
+        final int suggestionsHeight = (!mKeyboardSwitcher.isShowingEmojiPalettes()
+                && mSuggestionStripView.getVisibility() == View.VISIBLE)
+                ? mSuggestionStripView.getHeight() : 0;
+        final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight;
+        mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY);
+        // Need to set touchable region only if a keyboard view is being shown.
         if (visibleKeyboardView.isShown()) {
-            // Note that the height of Emoji layout is the same as the height of the main keyboard
-            // and the suggestion strip
-            if (mKeyboardSwitcher.isShowingEmojiPalettes()
-                    || mSuggestionStripView.getVisibility() == View.VISIBLE) {
-                visibleTopY -= suggestionsHeight;
-            }
-            final int touchY = mKeyboardSwitcher.isShowingMoreKeysPanel() ? 0 : visibleTopY;
-            final int touchWidth = visibleKeyboardView.getWidth();
-            final int touchHeight = visibleKeyboardView.getHeight() + extraHeight
+            final int touchLeft = 0;
+            final int touchTop = mKeyboardSwitcher.isShowingMoreKeysPanel() ? 0 : visibleTopY;
+            final int touchRight = visibleKeyboardView.getWidth();
+            final int touchBottom = inputHeight
                     // Extend touchable region below the keyboard.
                     + EXTENDED_TOUCHABLE_REGION_HEIGHT;
             outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION;
-            outInsets.touchableRegion.set(0, touchY, touchWidth, touchHeight);
+            outInsets.touchableRegion.set(touchLeft, touchTop, touchRight, touchBottom);
         }
         outInsets.contentTopInsets = visibleTopY;
         outInsets.visibleTopInsets = visibleTopY;
@@ -1173,12 +1147,28 @@
 
     @Override
     public void updateFullscreenMode() {
+        // Override layout parameters to expand {@link SoftInputWindow} to the entire screen.
+        // See {@link InputMethodService#setinputView(View) and
+        // {@link SoftInputWindow#updateWidthHeight(WindowManager.LayoutParams)}.
+        final Window window = getWindow().getWindow();
+        ViewLayoutUtils.updateLayoutHeightOf(window, LayoutParams.MATCH_PARENT);
+        // This method may be called before {@link #setInputView(View)}.
+        if (mInputView != null) {
+            // In non-fullscreen mode, {@link InputView} and its parent inputArea should expand to
+            // the entire screen and be placed at the bottom of {@link SoftInputWindow}.
+            // In fullscreen mode, these shouldn't expand to the entire screen and should be
+            // coexistent with {@link #mExtractedArea} above.
+            // See {@link InputMethodService#setInputView(View) and
+            // com.android.internal.R.layout.input_method.xml.
+            final int layoutHeight = isFullscreenMode()
+                    ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
+            final View inputArea = window.findViewById(android.R.id.inputArea);
+            ViewLayoutUtils.updateLayoutHeightOf(inputArea, layoutHeight);
+            ViewLayoutUtils.updateLayoutGravityOf(inputArea, Gravity.BOTTOM);
+            ViewLayoutUtils.updateLayoutHeightOf(mInputView, layoutHeight);
+        }
         super.updateFullscreenMode();
-
-        if (mKeyPreviewBackingView == null) return;
-        // In fullscreen mode, no need to have extra space to show the key preview.
-        // If not, we should have extra space above the keyboard to show the key preview.
-        mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE);
+        mInputLogic.onUpdateFullscreenMode(isFullscreenMode());
     }
 
     private int getCurrentAutoCapsState() {
@@ -1216,6 +1206,7 @@
             return;
         }
         mDictionaryFacilitator.addWordToUserDictionary(this /* context */, word);
+        mInputLogic.onAddWordToUserDictionary();
     }
 
     // Callback for the {@link SuggestionStripView}, to call when the important notice strip is
@@ -1412,7 +1403,8 @@
     }
 
     private void setSuggestedWords(final SuggestedWords suggestedWords) {
-        mInputLogic.setSuggestedWords(suggestedWords);
+        final SettingsValues currentSettingsValues = mSettings.getCurrent();
+        mInputLogic.setSuggestedWords(suggestedWords, currentSettingsValues, mHandler);
         // TODO: Modify this when we support suggestions with hard keyboard
         if (!hasSuggestionStripView()) {
             return;
@@ -1421,7 +1413,6 @@
             return;
         }
 
-        final SettingsValues currentSettingsValues = mSettings.getCurrent();
         final boolean shouldShowImportantNotice =
                 ImportantNoticeUtils.shouldShowImportantNotice(this);
         final boolean shouldShowSuggestionCandidates =
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 0355576..497823a 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -30,7 +30,9 @@
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
 
+import com.android.inputmethod.compat.InputConnectionCompatUtils;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.utils.CapsModeUtils;
 import com.android.inputmethod.latin.utils.DebugLogUtils;
@@ -906,4 +908,33 @@
             mIC.setSelection(mExpectedSelStart, mExpectedSelEnd);
         }
     }
+
+    private boolean mCursorAnchorInfoMonitorEnabled = false;
+
+    /**
+     * Requests the editor to call back {@link InputMethodManager#updateCursorAnchorInfo}.
+     * @param enableMonitor {@code true} to request the editor to call back the method whenever the
+     * cursor/anchor position is changed.
+     * @param requestImmediateCallback {@code true} to request the editor to call back the method
+     * as soon as possible to notify the current cursor/anchor position to the input method.
+     * @return {@code true} if the request is accepted. Returns {@code false} otherwise, which
+     * includes "not implemented" or "rejected" or "temporarily unavailable" or whatever which
+     * prevents the application from fulfilling the request. (TODO: Improve the API when it turns
+     * out that we actually need more detailed error codes)
+     */
+    public boolean requestUpdateCursorAnchorInfo(final boolean enableMonitor,
+            final boolean requestImmediateCallback) {
+        final boolean scheduled = InputConnectionCompatUtils.requestUpdateCursorAnchorInfo(mIC,
+                enableMonitor, requestImmediateCallback);
+        mCursorAnchorInfoMonitorEnabled = (scheduled && enableMonitor);
+        return scheduled;
+    }
+
+    /**
+     * @return {@code true} if the application reported that the monitor mode of
+     * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is currently enabled.
+     */
+    public boolean isCursorAnchorInfoMonitorEnabled() {
+        return mCursorAnchorInfoMonitorEnabled;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 790f72e..4b5edb0 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -17,9 +17,12 @@
 package com.android.inputmethod.latin.inputlogic;
 
 import android.graphics.Color;
+import android.inputmethodservice.InputMethodService;
 import android.os.SystemClock;
 import android.text.SpannableString;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.style.BackgroundColorSpan;
 import android.text.style.SuggestionSpan;
 import android.util.Log;
 import android.view.KeyCharacterMap;
@@ -27,11 +30,14 @@
 import android.view.inputmethod.CorrectionInfo;
 import android.view.inputmethod.EditorInfo;
 
+import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
 import com.android.inputmethod.compat.SuggestionSpanUtils;
 import com.android.inputmethod.event.Event;
 import com.android.inputmethod.event.InputTransaction;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.keyboard.TextDecorator;
+import com.android.inputmethod.keyboard.TextDecoratorUiOperator;
 import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.DictionaryFacilitator;
@@ -46,6 +52,7 @@
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.WordComposer;
 import com.android.inputmethod.latin.define.DebugFlags;
+import com.android.inputmethod.latin.define.ProductionFlags;
 import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
@@ -81,6 +88,18 @@
     public final Suggest mSuggest;
     private final DictionaryFacilitator mDictionaryFacilitator;
 
+    private final TextDecorator mTextDecorator = new TextDecorator(new TextDecorator.Listener() {
+        @Override
+        public void onClickComposingTextToCommit(SuggestedWordInfo wordInfo) {
+            mLatinIME.pickSuggestionManually(wordInfo);
+        }
+        @Override
+        public void onClickComposingTextToAddToDictionary(SuggestedWordInfo wordInfo) {
+            mLatinIME.addWordToUserDictionary(wordInfo.mWord);
+            mLatinIME.dismissAddToDictionaryHint();
+        }
+    });
+
     public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
     // This has package visibility so it can be accessed from InputLogicHandler.
     /* package */ final WordComposer mWordComposer;
@@ -124,8 +143,9 @@
      * Call this when input starts or restarts in some editor (typically, in onStartInputView).
      *
      * @param combiningSpec the combining spec string for this subtype
+     * @param settingsValues the current settings values
      */
-    public void startInput(final String combiningSpec) {
+    public void startInput(final String combiningSpec, final SettingsValues settingsValues) {
         mEnteredText = null;
         mWordComposer.restartCombining(combiningSpec);
         resetComposingState(true /* alsoResetLastComposedWord */);
@@ -143,15 +163,24 @@
         } else {
             mInputLogicHandler.reset();
         }
+
+        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
+            // AcceptTypedWord feature relies on CursorAnchorInfo.
+            if (settingsValues.mShouldShowUiToAcceptTypedWord) {
+                mConnection.requestUpdateCursorAnchorInfo(true /* enableMonitor */,
+                        true /* requestImmediateCallback */);
+            }
+        }
     }
 
     /**
      * Call this when the subtype changes.
      * @param combiningSpec the spec string for the combining rules
+     * @param settingsValues the current settings values
      */
-    public void onSubtypeChanged(final String combiningSpec) {
+    public void onSubtypeChanged(final String combiningSpec, final SettingsValues settingsValues) {
         finishInput();
-        startInput(combiningSpec);
+        startInput(combiningSpec, settingsValues);
     }
 
     /**
@@ -303,8 +332,18 @@
             return inputTransaction;
         }
 
-        commitChosenWord(settingsValues, suggestion,
-                LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR);
+        final boolean shouldShowAddToDictionaryHint = shouldShowAddToDictionaryHint(suggestionInfo);
+        final boolean shouldShowAddToDictionaryIndicator =
+                shouldShowAddToDictionaryHint && settingsValues.mShouldShowUiToAcceptTypedWord;
+        final int backgroundColor;
+        if (shouldShowAddToDictionaryIndicator) {
+            backgroundColor = settingsValues.mTextHighlightColorForAddToDictionaryIndicator;
+        } else {
+            backgroundColor = Color.TRANSPARENT;
+        }
+        commitChosenWordWithBackgroundColor(settingsValues, suggestion,
+                LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR,
+                backgroundColor);
         mConnection.endBatchEdit();
         // Don't allow cancellation of manual pick
         mLastComposedWord.deactivate();
@@ -312,13 +351,16 @@
         mSpaceState = SpaceState.PHANTOM;
         inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
 
-        if (shouldShowAddToDictionaryHint(suggestionInfo)) {
+        if (shouldShowAddToDictionaryHint) {
             mSuggestionStripViewAccessor.showAddToDictionaryHint(suggestion);
         } else {
             // If we're not showing the "Touch again to save", then update the suggestion strip.
             // That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
             handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
         }
+        if (shouldShowAddToDictionaryIndicator) {
+            mTextDecorator.showAddToDictionaryIndicator(suggestionInfo);
+        }
         return inputTransaction;
     }
 
@@ -386,6 +428,8 @@
 
         // The cursor has been moved : we now accept to perform recapitalization
         mRecapitalizeStatus.enable();
+        // We moved the cursor and need to invalidate the indicator right now.
+        mTextDecorator.reset();
         // We moved the cursor. If we are touching a word, we need to resume suggestion.
         mLatinIME.mHandler.postResumeSuggestions(false /* shouldIncludeResumedWordInSuggestions */,
                 true /* shouldDelay */);
@@ -561,7 +605,8 @@
 
     // TODO: on the long term, this method should become private, but it will be difficult.
     // Especially, how do we deal with InputMethodService.onDisplayCompletions?
-    public void setSuggestedWords(final SuggestedWords suggestedWords) {
+    public void setSuggestedWords(final SuggestedWords suggestedWords,
+            final SettingsValues settingsValues, final LatinIME.UIHandler handler) {
         if (SuggestedWords.EMPTY != suggestedWords) {
             final String autoCorrection;
             if (suggestedWords.mWillAutoCorrect) {
@@ -575,6 +620,43 @@
         }
         mSuggestedWords = suggestedWords;
         final boolean newAutoCorrectionIndicator = suggestedWords.mWillAutoCorrect;
+        if (shouldShowCommitIndicator(suggestedWords, settingsValues)) {
+            // typedWordInfo is never null here.
+            final int textBackgroundColor = settingsValues.mTextHighlightColorForCommitIndicator;
+            final SuggestedWordInfo typedWordInfo = suggestedWords.getTypedWordInfoOrNull();
+            handler.postShowCommitIndicatorTask(new Runnable() {
+                @Override
+                public void run() {
+                    // TODO: This needs to be refactored to ensure that mWordComposer is accessed
+                    // only from the UI thread.
+                    if (!mWordComposer.isComposingWord()) {
+                        mTextDecorator.reset();
+                        return;
+                    }
+                    final SuggestedWordInfo currentTypedWordInfo =
+                            mSuggestedWords.getTypedWordInfoOrNull();
+                    if (currentTypedWordInfo == null) {
+                        mTextDecorator.reset();
+                        return;
+                    }
+                    if (!currentTypedWordInfo.equals(typedWordInfo)) {
+                        // Suggested word has been changed. This task is obsolete.
+                        mTextDecorator.reset();
+                        return;
+                    }
+                    // TODO: As with the above TODO comment, this operation must be performed only
+                    // on the UI thread too. Needs to be refactored.
+                    setComposingTextInternalWithBackgroundColor(typedWordInfo.mWord,
+                            1 /* newCursorPosition */, textBackgroundColor);
+                    mTextDecorator.showCommitIndicator(typedWordInfo);
+                }
+            });
+        } else {
+            // Note: It is OK to not cancel previous postShowCommitIndicatorTask() here. Having a
+            // cancellation mechanism could improve performance a bit though.
+            mTextDecorator.reset();
+        }
+
         // Put a blue underline to a word in TextView which will be auto-corrected.
         if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator
                 && mWordComposer.isComposingWord()) {
@@ -585,7 +667,7 @@
             // message, this is called outside any batch edit. Potentially, this may result in some
             // janky flickering of the screen, although the display speed makes it unlikely in
             // the practice.
-            mConnection.setComposingText(textWithUnderline, 1);
+            setComposingTextInternal(textWithUnderline, 1);
         }
     }
 
@@ -608,7 +690,7 @@
             inputTransaction.setDidAffectContents();
         }
         if (mWordComposer.isComposingWord()) {
-            mConnection.setComposingText(mWordComposer.getTypedWord(), 1);
+            setComposingTextInternal(mWordComposer.getTypedWord(), 1);
             inputTransaction.setDidAffectContents();
             inputTransaction.setRequiresUpdateSuggestions();
         }
@@ -756,6 +838,8 @@
         if (!mWordComposer.isComposingWord() &&
                 mSuggestionStripViewAccessor.isShowingAddToDictionaryHint()) {
             mSuggestionStripViewAccessor.dismissAddToDictionaryHint();
+            mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
+            mTextDecorator.reset();
         }
 
         final int codePoint = event.mCodePoint;
@@ -842,8 +926,7 @@
             if (mWordComposer.isSingleLetter()) {
                 mWordComposer.setCapitalizedModeAtStartComposingTime(inputTransaction.mShiftState);
             }
-            mConnection.setComposingText(getTextWithUnderline(
-                    mWordComposer.getTypedWord()), 1);
+            setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
         } else {
             final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(event,
                     inputTransaction);
@@ -1006,7 +1089,7 @@
                 mWordComposer.applyProcessedEvent(event);
             }
             if (mWordComposer.isComposingWord()) {
-                mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
+                setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
             } else {
                 mConnection.commitText("", 1);
             }
@@ -1574,7 +1657,7 @@
             final int[] codePoints = StringUtils.toCodePointArray(stringToCommit);
             mWordComposer.setComposingWord(codePoints,
                     mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
-            mConnection.setComposingText(textToCommit, 1);
+            setComposingTextInternal(textToCommit, 1);
         }
         // Don't restart suggestion yet. We'll restart if the user deletes the separator.
         mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
@@ -1907,10 +1990,10 @@
             }
             final String lastWord = batchInputText.substring(indexOfLastSpace);
             mWordComposer.setBatchInputWord(lastWord);
-            mConnection.setComposingText(lastWord, 1);
+            setComposingTextInternal(lastWord, 1);
         } else {
             mWordComposer.setBatchInputWord(batchInputText);
-            mConnection.setComposingText(batchInputText, 1);
+            setComposingTextInternal(batchInputText, 1);
         }
         mConnection.endBatchEdit();
         // Space state must be updated before calling updateShiftState
@@ -2108,4 +2191,126 @@
                 settingsValues.mAutoCorrectionEnabledPerUserSettings,
                 inputStyle, sequenceNumber, callback);
     }
+
+    /**
+     * Used as an injection point for each call of
+     * {@link RichInputConnection#setComposingText(CharSequence, int)}.
+     *
+     * <p>Currently using this method is optional and you can still directly call
+     * {@link RichInputConnection#setComposingText(CharSequence, int)}, but it is recommended to
+     * use this method whenever possible to optimize the behavior of {@link TextDecorator}.<p>
+     * <p>TODO: Should we move this mechanism to {@link RichInputConnection}?</p>
+     *
+     * @param newComposingText the composing text to be set
+     * @param newCursorPosition the new cursor position
+     */
+    private void setComposingTextInternal(final CharSequence newComposingText,
+            final int newCursorPosition) {
+        setComposingTextInternalWithBackgroundColor(newComposingText, newCursorPosition,
+                Color.TRANSPARENT);
+    }
+
+    /**
+     * Equivalent to {@link #setComposingTextInternal(CharSequence, int)} except that this method
+     * allows to set {@link BackgroundColorSpan} to the composing text with the given color.
+     *
+     * <p>TODO: Currently the background color is exclusive with the black underline, which is
+     * automatically added by the framework. We need to change the framework if we need to have both
+     * of them at the same time.</p>
+     * <p>TODO: Should we move this method to {@link RichInputConnection}?</p>
+     *
+     * @param newComposingText the composing text to be set
+     * @param newCursorPosition the new cursor position
+     * @param backgroundColor the background color to be set to the composing text. Set
+     * {@link Color#TRANSPARENT} to disable the background color.
+     */
+    private void setComposingTextInternalWithBackgroundColor(final CharSequence newComposingText,
+            final int newCursorPosition, final int backgroundColor) {
+        final CharSequence composingTextToBeSet;
+        if (backgroundColor == Color.TRANSPARENT) {
+            composingTextToBeSet = newComposingText;
+        } else {
+            final SpannableString spannable = new SpannableString(newComposingText);
+            final BackgroundColorSpan backgroundColorSpan =
+                    new BackgroundColorSpan(backgroundColor);
+            spannable.setSpan(backgroundColorSpan, 0, spannable.length(),
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
+            composingTextToBeSet = spannable;
+        }
+        mConnection.setComposingText(composingTextToBeSet, newCursorPosition);
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // Following methods are tentatively placed in this class for the integration with
+    // TextDecorator.
+    // TODO: Decouple things that are not related to the input logic.
+    //////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Sets the UI operator for {@link TextDecorator}.
+     * @param uiOperator the UI operator which should be associated with {@link TextDecorator}.
+     */
+    public void setTextDecoratorUi(final TextDecoratorUiOperator uiOperator) {
+        mTextDecorator.setUiOperator(uiOperator);
+    }
+
+    /**
+     * Must be called from {@link InputMethodService#onUpdateCursorAnchorInfo} is called.
+     * @param info The wrapper object with which we can access cursor/anchor info.
+     */
+    public void onUpdateCursorAnchorInfo(final CursorAnchorInfoCompatWrapper info) {
+        mTextDecorator.onUpdateCursorAnchorInfo(info);
+    }
+
+    /**
+     * Must be called when {@link InputMethodService#updateFullscreenMode} is called.
+     * @param isFullscreen {@code true} if the input method is in full-screen mode.
+     */
+    public void onUpdateFullscreenMode(final boolean isFullscreen) {
+        mTextDecorator.notifyFullScreenMode(isFullscreen);
+    }
+
+    /**
+     * Must be called from {@link LatinIME#addWordToUserDictionary(String)}.
+     */
+    public void onAddWordToUserDictionary() {
+        mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
+        mTextDecorator.reset();
+    }
+
+    /**
+     * Returns whether the commit indicator should be shown or not.
+     * @param suggestedWords the suggested word that is being displayed.
+     * @param settingsValues the current settings value.
+     * @return {@code true} if the commit indicator should be shown.
+     */
+    private boolean shouldShowCommitIndicator(final SuggestedWords suggestedWords,
+            final SettingsValues settingsValues) {
+        if (!mConnection.isCursorAnchorInfoMonitorEnabled()) {
+            // We cannot help in this case because we are heavily relying on this new API.
+            return false;
+        }
+        if (!settingsValues.mShouldShowUiToAcceptTypedWord) {
+            return false;
+        }
+        final SuggestedWordInfo typedWordInfo = suggestedWords.getTypedWordInfoOrNull();
+        if (typedWordInfo == null) {
+            return false;
+        }
+        if (suggestedWords.mInputStyle != SuggestedWords.INPUT_STYLE_TYPING){
+            return false;
+        }
+        if (settingsValues.mShowCommitIndicatorOnlyForAutoCorrection
+                && !suggestedWords.mWillAutoCorrect) {
+            return false;
+        }
+        // TODO: Calling shouldShowAddToDictionaryHint(typedWordInfo) multiple times should be fine
+        // in terms of performance, but we can do better. One idea is to make SuggestedWords include
+        // a boolean that tells whether the word is a dictionary word or not.
+        if (settingsValues.mShowCommitIndicatorOnlyForOutOfVocabulary
+                && !shouldShowAddToDictionaryHint(typedWordInfo)) {
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index a9789d8..91a2b67 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -96,6 +96,12 @@
     public final int[] mAdditionalFeaturesSettingValues =
             new int[AdditionalFeaturesSettingUtils.ADDITIONAL_FEATURES_SETTINGS_SIZE];
 
+    // TextDecorator
+    public final int mTextHighlightColorForCommitIndicator;
+    public final int mTextHighlightColorForAddToDictionaryIndicator;
+    public final boolean mShowCommitIndicatorOnlyForAutoCorrection;
+    public final boolean mShowCommitIndicatorOnlyForOutOfVocabulary;
+
     // Debug settings
     public final boolean mIsInternal;
     public final int mKeyPreviewShowUpDuration;
@@ -164,6 +170,14 @@
         mSuggestionsEnabledPerUserSettings = readSuggestionsEnabled(prefs);
         AdditionalFeaturesSettingUtils.readAdditionalFeaturesPreferencesIntoArray(
                 prefs, mAdditionalFeaturesSettingValues);
+        mShowCommitIndicatorOnlyForAutoCorrection = res.getBoolean(
+                R.bool.text_decorator_only_for_auto_correction);
+        mShowCommitIndicatorOnlyForOutOfVocabulary = res.getBoolean(
+                R.bool.text_decorator_only_for_out_of_vocabulary);
+        mTextHighlightColorForCommitIndicator = res.getColor(
+                R.color.text_decorator_commit_indicator_text_highlight_color);
+        mTextHighlightColorForAddToDictionaryIndicator = res.getColor(
+                R.color.text_decorator_add_to_dictionary_indicator_text_highlight_color);
         mIsInternal = Settings.isInternal(prefs);
         mKeyPreviewShowUpDuration = Settings.readKeyPreviewAnimationDuration(
                 prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
@@ -401,6 +415,14 @@
         sb.append("" + (null == awu ? "null" : awu.toString()));
         sb.append("\n   mAdditionalFeaturesSettingValues = ");
         sb.append("" + Arrays.toString(mAdditionalFeaturesSettingValues));
+        sb.append("\n   mShowCommitIndicatorOnlyForAutoCorrection = ");
+        sb.append("" + mShowCommitIndicatorOnlyForAutoCorrection);
+        sb.append("\n   mShowCommitIndicatorOnlyForOutOfVocabulary = ");
+        sb.append("" + mShowCommitIndicatorOnlyForOutOfVocabulary);
+        sb.append("\n   mTextHighlightColorForCommitIndicator = ");
+        sb.append("" + mTextHighlightColorForCommitIndicator);
+        sb.append("\n   mTextHighlightColorForAddToDictionaryIndicator = ");
+        sb.append("" + mTextHighlightColorForAddToDictionaryIndicator);
         sb.append("\n   mIsInternal = ");
         sb.append("" + mIsInternal);
         sb.append("\n   mKeyPreviewShowUpDuration = ");
diff --git a/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java b/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java
index f9d8534..dd122b6 100644
--- a/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java
@@ -19,7 +19,10 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.MarginLayoutParams;
+import android.view.Window;
+import android.view.WindowManager;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 
 public final class ViewLayoutUtils {
@@ -51,4 +54,40 @@
             marginLayoutParams.setMargins(x, y, 0, 0);
         }
     }
+
+    public static void updateLayoutHeightOf(final Window window, final int layoutHeight) {
+        final WindowManager.LayoutParams params = window.getAttributes();
+        if (params.height != layoutHeight) {
+            params.height = layoutHeight;
+            window.setAttributes(params);
+        }
+    }
+
+    public static void updateLayoutHeightOf(final View view, final int layoutHeight) {
+        final ViewGroup.LayoutParams params = view.getLayoutParams();
+        if (params.height != layoutHeight) {
+            params.height = layoutHeight;
+            view.setLayoutParams(params);
+        }
+    }
+
+    public static void updateLayoutGravityOf(final View view, final int layoutGravity) {
+        final ViewGroup.LayoutParams lp = view.getLayoutParams();
+        if (lp instanceof LinearLayout.LayoutParams) {
+            final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)lp;
+            if (params.gravity != layoutGravity) {
+                params.gravity = layoutGravity;
+                view.setLayoutParams(params);
+            }
+        } else if (lp instanceof FrameLayout.LayoutParams) {
+            final FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)lp;
+            if (params.gravity != layoutGravity) {
+                params.gravity = layoutGravity;
+                view.setLayoutParams(params);
+            }
+        } else {
+            throw new IllegalArgumentException("Layout parameter doesn't have gravity: "
+                    + lp.getClass().getName());
+        }
+    }
 }
diff --git a/native/jni/NativeFileList.mk b/native/jni/NativeFileList.mk
index 5e66254..018a34d 100644
--- a/native/jni/NativeFileList.mk
+++ b/native/jni/NativeFileList.mk
@@ -61,7 +61,6 @@
         ver2_patricia_trie_node_reader.cpp \
         ver2_pt_node_array_reader.cpp) \
     $(addprefix suggest/policyimpl/dictionary/structure/v4/, \
-        bigram/ver4_bigram_list_policy.cpp \
         ver4_dict_buffers.cpp \
         ver4_dict_constants.cpp \
         ver4_patricia_trie_node_reader.cpp \
@@ -71,7 +70,6 @@
         ver4_patricia_trie_writing_helper.cpp \
         ver4_pt_node_array_reader.cpp) \
     $(addprefix suggest/policyimpl/dictionary/structure/v4/content/, \
-        bigram_dict_content.cpp \
         language_model_dict_content.cpp \
         shortcut_dict_content.cpp \
         sparse_table_dict_content.cpp \
@@ -132,4 +130,5 @@
     suggest/policyimpl/dictionary/utils/sparse_table_test.cpp \
     suggest/policyimpl/dictionary/utils/trie_map_test.cpp \
     utils/autocorrection_threshold_utils_test.cpp \
-    utils/int_array_view_test.cpp
+    utils/int_array_view_test.cpp \
+    utils/time_keeper_test.cpp
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 22ad2d0..81e2ff5 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -32,6 +32,7 @@
 #include "suggest/core/suggest_options.h"
 #include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
 #include "utils/char_utils.h"
+#include "utils/int_array_view.h"
 #include "utils/jni_data_utils.h"
 #include "utils/log_utils.h"
 #include "utils/time_keeper.h"
@@ -581,8 +582,9 @@
                 return false;
             }
         }
-        if (!dictionaryStructureWithBufferPolicy->addUnigramEntry(wordCodePoints,
-                wordCodePointCount, wordProperty.getUnigramProperty())) {
+        if (!dictionaryStructureWithBufferPolicy->addUnigramEntry(
+                CodePointArrayView(wordCodePoints, wordCodePointCount),
+                wordProperty.getUnigramProperty())) {
             LogUtils::logToJava(env, "Cannot add unigram to the new dict.");
             return false;
         }
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 24d04e5..57e1888 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -299,6 +299,7 @@
 #define NOT_AN_INDEX (-1)
 #define NOT_A_PROBABILITY (-1)
 #define NOT_A_DICT_POS (S_INT_MIN)
+#define NOT_A_WORD_ID (S_INT_MIN)
 #define NOT_A_TIMESTAMP (-1)
 #define NOT_A_LANGUAGE_WEIGHT (-1.0f)
 
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index d1b2c87..214cdfc 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -136,7 +136,7 @@
     }
 
     void initAsChild(const DicNode *const dicNode, const int ptNodePos,
-            const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
+            const int childrenPtNodeArrayPos, const int probability, const int wordId,
             const bool hasChildren, const bool isBlacklistedOrNotAWord,
             const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
         uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
@@ -144,7 +144,7 @@
         const uint16_t newLeavingDepth = static_cast<uint16_t>(
                 dicNode->mDicNodeProperties.getLeavingDepth() + mergedNodeCodePointCount);
         mDicNodeProperties.init(ptNodePos, childrenPtNodeArrayPos, mergedNodeCodePoints[0],
-                probability, isTerminal, hasChildren, isBlacklistedOrNotAWord, newDepth,
+                probability, wordId, hasChildren, isBlacklistedOrNotAWord, newDepth,
                 newLeavingDepth, dicNode->mDicNodeProperties.getPrevWordsTerminalPtNodePos());
         mDicNodeState.init(&dicNode->mDicNodeState, mergedNodeCodePointCount,
                 mergedNodeCodePoints);
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_vector.h b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
index 54cde19..f01640a 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_vector.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
@@ -59,13 +59,13 @@
     }
 
     void pushLeavingChild(const DicNode *const dicNode, const int ptNodePos,
-            const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
+            const int childrenPtNodeArrayPos, const int probability, const int wordId,
             const bool hasChildren, const bool isBlacklistedOrNotAWord,
             const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
         ASSERT(!mLock);
         mDicNodes.emplace_back();
         mDicNodes.back().initAsChild(dicNode, ptNodePos, childrenPtNodeArrayPos, probability,
-                isTerminal, hasChildren, isBlacklistedOrNotAWord, mergedNodeCodePointCount,
+                wordId, hasChildren, isBlacklistedOrNotAWord, mergedNodeCodePointCount,
                 mergedNodeCodePoints);
     }
 
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
index 8202176..fc242a9 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
@@ -31,20 +31,20 @@
     AK_FORCE_INLINE DicNodeProperties()
             : mPtNodePos(NOT_A_DICT_POS), mChildrenPtNodeArrayPos(NOT_A_DICT_POS),
               mProbability(NOT_A_PROBABILITY), mDicNodeCodePoint(NOT_A_CODE_POINT),
-              mIsTerminal(false), mHasChildrenPtNodes(false),
+              mWordId(NOT_A_WORD_ID), mHasChildrenPtNodes(false),
               mIsBlacklistedOrNotAWord(false), mDepth(0), mLeavingDepth(0) {}
 
     ~DicNodeProperties() {}
 
     // Should be called only once per DicNode is initialized.
     void init(const int pos, const int childrenPos, const int nodeCodePoint, const int probability,
-            const bool isTerminal, const bool hasChildren, const bool isBlacklistedOrNotAWord,
+            const int wordId, const bool hasChildren, const bool isBlacklistedOrNotAWord,
             const uint16_t depth, const uint16_t leavingDepth, const int *const prevWordsNodePos) {
         mPtNodePos = pos;
         mChildrenPtNodeArrayPos = childrenPos;
         mDicNodeCodePoint = nodeCodePoint;
         mProbability = probability;
-        mIsTerminal = isTerminal;
+        mWordId = wordId;
         mHasChildrenPtNodes = hasChildren;
         mIsBlacklistedOrNotAWord = isBlacklistedOrNotAWord;
         mDepth = depth;
@@ -58,7 +58,7 @@
         mChildrenPtNodeArrayPos = rootPtNodeArrayPos;
         mDicNodeCodePoint = NOT_A_CODE_POINT;
         mProbability = NOT_A_PROBABILITY;
-        mIsTerminal = false;
+        mWordId = NOT_A_WORD_ID;
         mHasChildrenPtNodes = true;
         mIsBlacklistedOrNotAWord = false;
         mDepth = 0;
@@ -71,7 +71,7 @@
         mChildrenPtNodeArrayPos = dicNodeProp->mChildrenPtNodeArrayPos;
         mDicNodeCodePoint = dicNodeProp->mDicNodeCodePoint;
         mProbability = dicNodeProp->mProbability;
-        mIsTerminal = dicNodeProp->mIsTerminal;
+        mWordId = dicNodeProp->mWordId;
         mHasChildrenPtNodes = dicNodeProp->mHasChildrenPtNodes;
         mIsBlacklistedOrNotAWord = dicNodeProp->mIsBlacklistedOrNotAWord;
         mDepth = dicNodeProp->mDepth;
@@ -86,7 +86,7 @@
         mChildrenPtNodeArrayPos = dicNodeProp->mChildrenPtNodeArrayPos;
         mDicNodeCodePoint = codePoint; // Overwrite the node char of a passing child
         mProbability = dicNodeProp->mProbability;
-        mIsTerminal = dicNodeProp->mIsTerminal;
+        mWordId = dicNodeProp->mWordId;
         mHasChildrenPtNodes = dicNodeProp->mHasChildrenPtNodes;
         mIsBlacklistedOrNotAWord = dicNodeProp->mIsBlacklistedOrNotAWord;
         mDepth = dicNodeProp->mDepth + 1; // Increment the depth of a passing child
@@ -121,7 +121,7 @@
     }
 
     bool isTerminal() const {
-        return mIsTerminal;
+        return mWordId != NOT_A_WORD_ID;
     }
 
     bool hasChildren() const {
@@ -144,7 +144,7 @@
     int mChildrenPtNodeArrayPos;
     int mProbability;
     int mDicNodeCodePoint;
-    bool mIsTerminal;
+    int mWordId;
     bool mHasChildrenPtNodes;
     bool mIsBlacklistedOrNotAWord;
     uint16_t mDepth;
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index d625739..c025bfc 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -28,6 +28,7 @@
 #include "suggest/core/suggest_options.h"
 #include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
 #include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
+#include "utils/int_array_view.h"
 #include "utils/log_utils.h"
 #include "utils/time_keeper.h"
 
@@ -112,8 +113,8 @@
 int Dictionary::getNgramProbability(const PrevWordsInfo *const prevWordsInfo, const int *word,
         int length) const {
     TimeKeeper::setCurrentTime();
-    int nextWordPos = mDictionaryStructureWithBufferPolicy->getTerminalPtNodePositionOfWord(word,
-            length, false /* forceLowerCaseSearch */);
+    int nextWordPos = mDictionaryStructureWithBufferPolicy->getTerminalPtNodePositionOfWord(
+            CodePointArrayView(word, length), false /* forceLowerCaseSearch */);
     if (NOT_A_DICT_POS == nextWordPos) return NOT_A_PROBABILITY;
     if (!prevWordsInfo) {
         return getDictionaryStructurePolicy()->getProbabilityOfPtNode(
@@ -135,12 +136,14 @@
         return false;
     }
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->addUnigramEntry(word, length, unigramProperty);
+    return mDictionaryStructureWithBufferPolicy->addUnigramEntry(CodePointArrayView(word, length),
+            unigramProperty);
 }
 
 bool Dictionary::removeUnigramEntry(const int *const codePoints, const int codePointCount) {
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->removeUnigramEntry(codePoints, codePointCount);
+    return mDictionaryStructureWithBufferPolicy->removeUnigramEntry(
+            CodePointArrayView(codePoints, codePointCount));
 }
 
 bool Dictionary::addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
@@ -152,7 +155,8 @@
 bool Dictionary::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
         const int *const word, const int length) {
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->removeNgramEntry(prevWordsInfo, word, length);
+    return mDictionaryStructureWithBufferPolicy->removeNgramEntry(prevWordsInfo,
+            CodePointArrayView(word, length));
 }
 
 bool Dictionary::flush(const char *const filePath) {
@@ -181,7 +185,7 @@
         const int codePointCount) {
     TimeKeeper::setCurrentTime();
     return mDictionaryStructureWithBufferPolicy->getWordProperty(
-            codePoints, codePointCount);
+            CodePointArrayView(codePoints, codePointCount));
 }
 
 int Dictionary::getNextWordAndNextToken(const int token, int *const outCodePoints,
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.cpp b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
index 5bdd560..66daf3e 100644
--- a/native/jni/src/suggest/core/dictionary/property/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
@@ -65,8 +65,6 @@
     for (const auto &shortcut : mUnigramProperty.getShortcuts()) {
         const std::vector<int> *const targetCodePoints = shortcut.getTargetCodePoints();
         jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
-        env->SetIntArrayRegion(shortcutTargetCodePointArray, 0 /* start */,
-                targetCodePoints->size(), targetCodePoints->data());
         JniDataUtils::outputCodePoints(env, shortcutTargetCodePointArray, 0 /* start */,
                 targetCodePoints->size(), targetCodePoints->data(), targetCodePoints->size(),
                 false /* needsNullTermination */);
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
index e91f076..0faf000 100644
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
@@ -21,6 +21,7 @@
 
 #include "defines.h"
 #include "suggest/core/dictionary/property/word_property.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -36,6 +37,7 @@
  * This class abstracts the structure of dictionaries.
  * Implement this policy to support additional dictionaries.
  */
+// TODO: Use word id instead of terminal PtNode position.
 class DictionaryStructureWithBufferPolicy {
  public:
     typedef std::unique_ptr<DictionaryStructureWithBufferPolicy> StructurePolicyPtr;
@@ -48,33 +50,32 @@
             DicNodeVector *const childDicNodes) const = 0;
 
     virtual int getCodePointsAndProbabilityAndReturnCodePointCount(
-            const int nodePos, const int maxCodePointCount, int *const outCodePoints,
+            const int ptNodePos, const int maxCodePointCount, int *const outCodePoints,
             int *const outUnigramProbability) const = 0;
 
-    virtual int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const = 0;
+    virtual int getTerminalPtNodePositionOfWord(const CodePointArrayView wordCodePoints,
+            const bool forceLowerCaseSearch) const = 0;
 
-    virtual int getProbability(const int unigramProbability,
-            const int bigramProbability) const = 0;
+    virtual int getProbability(const int unigramProbability, const int bigramProbability) const = 0;
 
     virtual int getProbabilityOfPtNode(const int *const prevWordsPtNodePos,
-            const int nodePos) const = 0;
+            const int ptNodePos) const = 0;
 
     virtual void iterateNgramEntries(const int *const prevWordsPtNodePos,
             NgramListener *const listener) const = 0;
 
-    virtual int getShortcutPositionOfPtNode(const int nodePos) const = 0;
+    virtual int getShortcutPositionOfPtNode(const int ptNodePos) const = 0;
 
     virtual const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const = 0;
 
     virtual const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const = 0;
 
     // Returns whether the update was success or not.
-    virtual bool addUnigramEntry(const int *const word, const int length,
+    virtual bool addUnigramEntry(const CodePointArrayView wordCodePoints,
             const UnigramProperty *const unigramProperty) = 0;
 
     // Returns whether the update was success or not.
-    virtual bool removeUnigramEntry(const int *const word, const int length) = 0;
+    virtual bool removeUnigramEntry(const CodePointArrayView wordCodePoints) = 0;
 
     // Returns whether the update was success or not.
     virtual bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
@@ -82,7 +83,7 @@
 
     // Returns whether the update was success or not.
     virtual bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-            const int *const word, const int length) = 0;
+            const CodePointArrayView wordCodePoints) = 0;
 
     // Returns whether the flush was success or not.
     virtual bool flush(const char *const filePath) = 0;
@@ -98,8 +99,7 @@
             const int maxResultLength) = 0;
 
     // Used for testing.
-    virtual const WordProperty getWordProperty(const int *const codePonts,
-            const int codePointCount) const = 0;
+    virtual const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const = 0;
 
     // Method to iterate all words in the dictionary.
     // The returned token has to be used to get the next word. If token is 0, this method newly
diff --git a/native/jni/src/suggest/core/session/prev_words_info.h b/native/jni/src/suggest/core/session/prev_words_info.h
index e44e876..9b3a7d4 100644
--- a/native/jni/src/suggest/core/session/prev_words_info.h
+++ b/native/jni/src/suggest/core/session/prev_words_info.h
@@ -21,6 +21,7 @@
 #include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h"
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 #include "utils/char_utils.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -91,19 +92,11 @@
     }
 
     // n is 1-indexed.
-    const int *getNthPrevWordCodePoints(const int n) const {
+    const CodePointArrayView getNthPrevWordCodePoints(const int n) const {
         if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
-            return nullptr;
+            return CodePointArrayView();
         }
-        return mPrevWordCodePoints[n - 1];
-    }
-
-    // n is 1-indexed.
-    int getNthPrevWordCodePointCount(const int n) const {
-        if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
-            return 0;
-        }
-        return mPrevWordCodePointCount[n - 1];
+        return CodePointArrayView(mPrevWordCodePoints[n - 1], mPrevWordCodePointCount[n - 1]);
     }
 
     // n is 1-indexed.
@@ -134,8 +127,9 @@
                 return NOT_A_DICT_POS;
             }
         }
+        const CodePointArrayView codePointArrayView(codePoints, codePointCount);
         const int wordPtNodePos = dictStructurePolicy->getTerminalPtNodePositionOfWord(
-                codePoints, codePointCount, false /* forceLowerCaseSearch */);
+                codePointArrayView, false /* forceLowerCaseSearch */);
         if (wordPtNodePos != NOT_A_DICT_POS || !tryLowerCaseSearch) {
             // Return the position when when the word was found or doesn't try lower case
             // search.
@@ -144,7 +138,7 @@
         // Check bigrams for lower-cased previous word if original was not found. Useful for
         // auto-capitalized words like "The [current_word]".
         return dictStructurePolicy->getTerminalPtNodePositionOfWord(
-                codePoints, codePointCount, true /* forceLowerCaseSearch */);
+                codePointArrayView, true /* forceLowerCaseSearch */);
     }
 
     void clear() {
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 9c6452e..9f6ae11 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
@@ -76,8 +76,9 @@
             // Skip PtNodes that represent non-word information.
             continue;
         }
+        const int wordId = isTerminal ? ptNodeParams.getHeadPos() : NOT_A_WORD_ID;
         childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
-                ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
+                ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), wordId,
                 ptNodeParams.hasChildren(),
                 ptNodeParams.isBlacklisted()
                         || ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */,
@@ -103,12 +104,12 @@
     return codePointCount;
 }
 
-int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) const {
+int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const CodePointArrayView wordCodePoints,
+        const bool forceLowerCaseSearch) const {
     DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
     readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    const int ptNodePos =
-            readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch);
+    const int ptNodePos = readingHelper.getTerminalPtNodePositionOfWord(wordCodePoints.data(),
+            wordCodePoints.size(), forceLowerCaseSearch);
     if (readingHelper.isError()) {
         mIsCorrupted = true;
         AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
@@ -193,7 +194,7 @@
             ptNodeParams.getTerminalId());
 }
 
-bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int length,
+bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePoints,
         const UnigramProperty *const unigramProperty) {
     if (!mBuffers->isUpdatable()) {
         AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
@@ -204,8 +205,9 @@
                 mDictBuffer->getTailPosition());
         return false;
     }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("The word is too long to insert to the dictionary, length: %d", length);
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("The word is too long to insert to the dictionary, length: %zd",
+                wordCodePoints.size());
         return false;
     }
     for (const auto &shortcut : unigramProperty->getShortcuts()) {
@@ -219,8 +221,8 @@
     readingHelper.initWithPtNodeArrayPos(getRootPosition());
     bool addedNewUnigram = false;
     int codePointsToAdd[MAX_WORD_LENGTH];
-    int codePointCountToAdd = length;
-    memmove(codePointsToAdd, word, sizeof(int) * length);
+    int codePointCountToAdd = wordCodePoints.size();
+    memmove(codePointsToAdd, wordCodePoints.data(), sizeof(int) * codePointCountToAdd);
     if (unigramProperty->representsBeginningOfSentence()) {
         codePointCountToAdd = CharUtils::attachBeginningOfSentenceMarker(codePointsToAdd,
                 codePointCountToAdd, MAX_WORD_LENGTH);
@@ -228,14 +230,15 @@
     if (codePointCountToAdd <= 0) {
         return false;
     }
-    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointsToAdd, codePointCountToAdd,
-            unigramProperty, &addedNewUnigram)) {
+    const CodePointArrayView codePointArrayView(codePointsToAdd, codePointCountToAdd);
+    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView.data(),
+            codePointArrayView.size(), unigramProperty, &addedNewUnigram)) {
         if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
             mUnigramCount++;
         }
         if (unigramProperty->getShortcuts().size() > 0) {
             // Add shortcut target.
-            const int wordPos = getTerminalPtNodePositionOfWord(word, length,
+            const int wordPos = getTerminalPtNodePositionOfWord(codePointArrayView,
                     false /* forceLowerCaseSearch */);
             if (wordPos == NOT_A_DICT_POS) {
                 AKLOGE("Cannot find terminal PtNode position to add shortcut target.");
@@ -258,12 +261,12 @@
     }
 }
 
-bool Ver4PatriciaTriePolicy::removeUnigramEntry(const int *const word, const int length) {
+bool Ver4PatriciaTriePolicy::removeUnigramEntry(const CodePointArrayView wordCodePoints) {
     if (!mBuffers->isUpdatable()) {
         AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
         return false;
     }
-    const int ptNodePos = getTerminalPtNodePositionOfWord(word, length,
+    const int ptNodePos = getTerminalPtNodePositionOfWord(wordCodePoints,
             false /* forceLowerCaseSearch */);
     if (ptNodePos == NOT_A_DICT_POS) {
         return false;
@@ -304,7 +307,6 @@
                     false /* isBlacklisted */, MAX_PROBABILITY /* probability */,
                     NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
             if (!addUnigramEntry(prevWordsInfo->getNthPrevWordCodePoints(1 /* n */),
-                    prevWordsInfo->getNthPrevWordCodePointCount(1 /* n */),
                     &beginningOfSentenceUnigramProperty)) {
                 AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
                 return false;
@@ -317,8 +319,8 @@
         }
     }
     const int word1Pos = getTerminalPtNodePositionOfWord(
-            bigramProperty->getTargetCodePoints()->data(),
-            bigramProperty->getTargetCodePoints()->size(), false /* forceLowerCaseSearch */);
+            CodePointArrayView(*bigramProperty->getTargetCodePoints()),
+            false /* forceLowerCaseSearch */);
     if (word1Pos == NOT_A_DICT_POS) {
         return false;
     }
@@ -335,7 +337,7 @@
 }
 
 bool Ver4PatriciaTriePolicy::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const int *const word, const int length) {
+        const CodePointArrayView wordCodePoints) {
     if (!mBuffers->isUpdatable()) {
         AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
         return false;
@@ -349,8 +351,9 @@
         AKLOGE("prev words info is not valid for removing n-gram entry form the dictionary.");
         return false;
     }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %d", length);
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %zd",
+                wordCodePoints.size());
     }
     int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
     prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
@@ -359,7 +362,7 @@
     if (prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
         return false;
     }
-    const int wordPos = getTerminalPtNodePositionOfWord(word, length,
+    const int wordPos = getTerminalPtNodePositionOfWord(wordCodePoints,
             false /* forceLowerCaseSearch */);
     if (wordPos == NOT_A_DICT_POS) {
         return false;
@@ -444,9 +447,9 @@
     }
 }
 
-const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const codePoints,
-        const int codePointCount) const {
-    const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
+const WordProperty Ver4PatriciaTriePolicy::getWordProperty(
+        const CodePointArrayView wordCodePoints) const {
+    const int ptNodePos = getTerminalPtNodePositionOfWord(wordCodePoints,
             false /* forceLowerCaseSearch */);
     if (ptNodePos == NOT_A_DICT_POS) {
         AKLOGE("getWordProperty is called for invalid word.");
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 d774996..df119e3 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
@@ -39,6 +39,7 @@
 #include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h"
 #include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h"
 #include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 namespace backward {
@@ -55,6 +56,7 @@
 namespace backward {
 namespace v402 {
 
+// Word id = Position of a PtNode that represents the word.
 class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
  public:
     Ver4PatriciaTriePolicy(Ver4DictBuffers::Ver4DictBuffersPtr buffers)
@@ -74,7 +76,7 @@
               mBigramCount(mHeaderPolicy->getBigramCount()),
               mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {};
 
-    AK_FORCE_INLINE int getRootPosition() const {
+    virtual int getRootPosition() const {
         return 0;
     }
 
@@ -85,8 +87,8 @@
             const int terminalPtNodePos, const int maxCodePointCount, int *const outCodePoints,
             int *const outUnigramProbability) const;
 
-    int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const;
+    int getTerminalPtNodePositionOfWord(const CodePointArrayView wordCodePoints,
+            const bool forceLowerCaseSearch) const;
 
     int getProbability(const int unigramProbability, const int bigramProbability) const;
 
@@ -105,16 +107,16 @@
         return &mShortcutPolicy;
     }
 
-    bool addUnigramEntry(const int *const word, const int length,
+    bool addUnigramEntry(const CodePointArrayView wordCodePoints,
             const UnigramProperty *const unigramProperty);
 
-    bool removeUnigramEntry(const int *const word, const int length);
+    bool removeUnigramEntry(const CodePointArrayView wordCodePoints);
 
     bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
             const BigramProperty *const bigramProperty);
 
-    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word1,
-            const int length1);
+    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
+            const CodePointArrayView wordCodePoints);
 
     bool flush(const char *const filePath);
 
@@ -125,8 +127,7 @@
     void getProperty(const char *const query, const int queryLength, char *const outResult,
             const int maxResultLength);
 
-    const WordProperty getWordProperty(const int *const codePoints,
-            const int codePointCount) const;
+    const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const;
 
     int getNextWordAndNextToken(const int token, int *const outCodePoints,
             int *const outCodePointCount);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index ea32eb2..4ac366e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -268,12 +268,12 @@
 
 // This function gets the position of the terminal PtNode of the exact matching word in the
 // dictionary. If no match is found, it returns NOT_A_DICT_POS.
-int PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) const {
+int PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const CodePointArrayView wordCodePoints,
+        const bool forceLowerCaseSearch) const {
     DynamicPtReadingHelper readingHelper(&mPtNodeReader, &mPtNodeArrayReader);
     readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    const int ptNodePos =
-            readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch);
+    const int ptNodePos = readingHelper.getTerminalPtNodePositionOfWord(wordCodePoints.data(),
+            wordCodePoints.size(), forceLowerCaseSearch);
     if (readingHelper.isError()) {
         mIsCorrupted = true;
         AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
@@ -367,8 +367,8 @@
             &probability, &childrenPos, &shortcutPos, &bigramPos, &siblingPos);
     // Skip PtNodes don't start with Unicode code point because they represent non-word information.
     if (CharUtils::isInUnicodeSpace(mergedNodeCodePoints[0])) {
-        childDicNodes->pushLeavingChild(dicNode, ptNodePos, childrenPos, probability,
-                PatriciaTrieReadingUtils::isTerminal(flags),
+        const int wordId = PatriciaTrieReadingUtils::isTerminal(flags) ? ptNodePos : NOT_A_WORD_ID;
+        childDicNodes->pushLeavingChild(dicNode, ptNodePos, childrenPos, probability, wordId,
                 PatriciaTrieReadingUtils::hasChildrenInFlags(flags),
                 PatriciaTrieReadingUtils::isBlacklisted(flags)
                         || PatriciaTrieReadingUtils::isNotAWord(flags),
@@ -377,9 +377,9 @@
     return siblingPos;
 }
 
-const WordProperty PatriciaTriePolicy::getWordProperty(const int *const codePoints,
-        const int codePointCount) const {
-    const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
+const WordProperty PatriciaTriePolicy::getWordProperty(
+        const CodePointArrayView wordCodePoints) const {
+    const int ptNodePos = getTerminalPtNodePositionOfWord(wordCodePoints,
             false /* forceLowerCaseSearch */);
     if (ptNodePos == NOT_A_DICT_POS) {
         AKLOGE("getWordProperty was called for invalid word.");
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
index 70351d1..4d9af28 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
@@ -30,12 +30,14 @@
 #include "suggest/policyimpl/dictionary/utils/format_utils.h"
 #include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
 #include "utils/byte_array_view.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
 class DicNode;
 class DicNodeVector;
 
+// Word id = Position of a PtNode that represents the word.
 class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
  public:
     PatriciaTriePolicy(MmappedBuffer::MmappedBufferPtr mmappedBuffer)
@@ -62,8 +64,8 @@
             const int terminalNodePos, const int maxCodePointCount, int *const outCodePoints,
             int *const outUnigramProbability) const;
 
-    int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const;
+    int getTerminalPtNodePositionOfWord(const CodePointArrayView wordCodePoints,
+            const bool forceLowerCaseSearch) const;
 
     int getProbability(const int unigramProbability, const int bigramProbability) const;
 
@@ -82,14 +84,14 @@
         return &mShortcutListPolicy;
     }
 
-    bool addUnigramEntry(const int *const word, const int length,
+    bool addUnigramEntry(const CodePointArrayView wordCodePoints,
             const UnigramProperty *const unigramProperty) {
         // This method should not be called for non-updatable dictionary.
         AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
         return false;
     }
 
-    bool removeUnigramEntry(const int *const word, const int length) {
+    bool removeUnigramEntry(const CodePointArrayView wordCodePoints) {
         // This method should not be called for non-updatable dictionary.
         AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
         return false;
@@ -102,8 +104,8 @@
         return false;
     }
 
-    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word,
-            const int length) {
+    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
+            const CodePointArrayView wordCodePoints) {
         // This method should not be called for non-updatable dictionary.
         AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
         return false;
@@ -135,8 +137,7 @@
         }
     }
 
-    const WordProperty getWordProperty(const int *const codePoints,
-            const int codePointCount) const;
+    const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const;
 
     int getNextWordAndNextToken(const int token, int *const outCodePoints,
             int *const outCodePointCount);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
deleted file mode 100644
index 08dc107..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
-
-#include "suggest/core/dictionary/property/bigram_property.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-
-void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const outProbability,
-        bool *const outHasNext, int *const bigramEntryPos) const {
-    const BigramEntry bigramEntry =
-            mBigramDictContent->getBigramEntryAndAdvancePosition(bigramEntryPos);
-    if (outBigramPos) {
-        // Lookup target PtNode position.
-        *outBigramPos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
-                bigramEntry.getTargetTerminalId());
-    }
-    if (outProbability) {
-        if (bigramEntry.hasHistoricalInfo()) {
-            *outProbability =
-                    ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo(),
-                            mHeaderPolicy);
-        } else {
-            *outProbability = bigramEntry.getProbability();
-        }
-    }
-    if (outHasNext) {
-        *outHasNext = bigramEntry.hasNext();
-    }
-}
-
-bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId,
-        const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
-    // 1. The word has no bigrams yet.
-    // 2. The word has bigrams, and there is the target in the list.
-    // 3. The word has bigrams, and there is an invalid entry that can be reclaimed.
-    // 4. The word has bigrams. We have to append new bigram entry to the list.
-    // 5. Same as 4, but the list is the last entry of the content file.
-    if (outAddedNewEntry) {
-        *outAddedNewEntry = false;
-    }
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Case 1. PtNode that doesn't have a bigram list.
-        // Create new bigram list.
-        if (!mBigramDictContent->createNewBigramList(terminalId)) {
-            return false;
-        }
-        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry,
-                bigramProperty);
-        // Write an entry.
-        int writingPos =  mBigramDictContent->getBigramListHeadPos(terminalId);
-        if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite,
-                &writingPos)) {
-            AKLOGE("Cannot write bigram entry. pos: %d.", writingPos);
-            return false;
-        }
-        if (!mBigramDictContent->writeTerminator(writingPos)) {
-            AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos);
-            return false;
-        }
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-        return true;
-    }
-
-    int tailEntryPos = NOT_A_DICT_POS;
-    const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos,
-            &tailEntryPos);
-    if (entryPosToUpdate == NOT_A_DICT_POS) {
-        // Case 4, 5. Add new entry to the bigram list.
-        const int contentTailPos = mBigramDictContent->getContentTailPos();
-        // If the tail entry is at the tail of content buffer, the new entry can be written without
-        // link (Case 5).
-        const bool canAppendEntry =
-                contentTailPos == tailEntryPos + mBigramDictContent->getBigramEntrySize();
-        const int newEntryPos = canAppendEntry ? tailEntryPos : contentTailPos;
-        int writingPos = newEntryPos;
-        // Write new entry at the tail position of the bigram content.
-        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
-                &newBigramEntry, bigramProperty);
-        if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite,
-                &writingPos)) {
-            AKLOGE("Cannot write bigram entry. pos: %d.", writingPos);
-            return false;
-        }
-        if (!mBigramDictContent->writeTerminator(writingPos)) {
-            AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos);
-            return false;
-        }
-        if (!canAppendEntry) {
-            // Update link of the current tail entry.
-            if (!mBigramDictContent->writeLink(newEntryPos, tailEntryPos)) {
-                AKLOGE("Cannot update bigram entry link. pos: %d, linked entry pos: %d.",
-                        tailEntryPos, newEntryPos);
-                return false;
-            }
-        }
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-        return true;
-    }
-
-    // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry.
-    const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
-    if (!originalBigramEntry.isValid()) {
-        // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing
-        // entry is updated.
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-    }
-    const BigramEntry updatedBigramEntry =
-            originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId);
-    const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
-            &updatedBigramEntry, bigramProperty);
-    return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate);
-}
-
-bool Ver4BigramListPolicy::removeEntry(const int terminalId, const int targetTerminalId) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return false;
-    }
-    const int entryPosToUpdate = getEntryPosToUpdate(targetTerminalId, bigramListPos,
-            nullptr /* outTailEntryPos */);
-    if (entryPosToUpdate == NOT_A_DICT_POS) {
-        // Bigram entry doesn't exist.
-        return false;
-    }
-    const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
-    if (targetTerminalId != bigramEntry.getTargetTerminalId()) {
-        // Bigram entry doesn't exist.
-        return false;
-    }
-    // Remove bigram entry by marking it as invalid entry and overwriting the original entry.
-    const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-    return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPosToUpdate);
-}
-
-bool Ver4BigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
-        int *const outBigramCount) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return true;
-    }
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    while (hasNext) {
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        const int entryPos = readingPos - mBigramDictContent->getBigramEntrySize();
-        hasNext = bigramEntry.hasNext();
-        if (!bigramEntry.isValid()) {
-            continue;
-        }
-        const int targetPtNodePos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
-                bigramEntry.getTargetTerminalId());
-        if (targetPtNodePos == NOT_A_DICT_POS) {
-            // Invalidate bigram entry.
-            const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-            if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                return false;
-            }
-        } else if (bigramEntry.hasHistoricalInfo()) {
-            const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
-                    bigramEntry.getHistoricalInfo(), mHeaderPolicy);
-            if (ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy)) {
-                const BigramEntry updatedBigramEntry =
-                        bigramEntry.updateHistoricalInfoAndGetEntry(&historicalInfo);
-                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                    return false;
-                }
-                *outBigramCount += 1;
-            } else {
-                // Remove entry.
-                const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                    return false;
-                }
-            }
-        } else {
-            *outBigramCount += 1;
-        }
-    }
-    return true;
-}
-
-int Ver4BigramListPolicy::getBigramEntryConut(const int terminalId) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return 0;
-    }
-    int bigramCount = 0;
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    while (hasNext) {
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = bigramEntry.hasNext();
-        if (bigramEntry.isValid()) {
-            bigramCount++;
-        }
-    }
-    return bigramCount;
-}
-
-int Ver4BigramListPolicy::getEntryPosToUpdate(const int targetTerminalIdToFind,
-        const int bigramListPos, int *const outTailEntryPos) const {
-    if (outTailEntryPos) {
-        *outTailEntryPos = NOT_A_DICT_POS;
-    }
-    int invalidEntryPos = NOT_A_DICT_POS;
-    int readingPos = bigramListPos;
-    while (true) {
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        const int entryPos = readingPos - mBigramDictContent->getBigramEntrySize();
-        if (!bigramEntry.hasNext()) {
-            if (outTailEntryPos) {
-                *outTailEntryPos = entryPos;
-            }
-            break;
-        }
-        if (bigramEntry.getTargetTerminalId() == targetTerminalIdToFind) {
-            // Entry with same target is found.
-            return entryPos;
-        } else if (!bigramEntry.isValid()) {
-            // Invalid entry that can be reused is found.
-            invalidEntryPos = entryPos;
-        }
-    }
-    return invalidEntryPos;
-}
-
-const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom(
-        const BigramEntry *const originalBigramEntry,
-        const BigramProperty *const bigramProperty) const {
-    // TODO: Consolidate historical info and probability.
-    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(bigramProperty->getTimestamp(),
-                bigramProperty->getLevel(), bigramProperty->getCount());
-        const HistoricalInfo updatedHistoricalInfo =
-                ForgettingCurveUtils::createUpdatedHistoricalInfo(
-                        originalBigramEntry->getHistoricalInfo(), bigramProperty->getProbability(),
-                        &historicalInfoForUpdate, mHeaderPolicy);
-        return originalBigramEntry->updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo);
-    } else {
-        return originalBigramEntry->updateProbabilityAndGetEntry(bigramProperty->getProbability());
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
deleted file mode 100644
index 4b3bb37..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef LATINIME_VER4_BIGRAM_LIST_POLICY_H
-#define LATINIME_VER4_BIGRAM_LIST_POLICY_H
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h"
-
-namespace latinime {
-
-class BigramDictContent;
-class BigramProperty;
-class HeaderPolicy;
-class TerminalPositionLookupTable;
-
-class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy {
- public:
-    Ver4BigramListPolicy(BigramDictContent *const bigramDictContent,
-            const TerminalPositionLookupTable *const terminalPositionLookupTable,
-            const HeaderPolicy *const headerPolicy)
-            : mBigramDictContent(bigramDictContent),
-              mTerminalPositionLookupTable(terminalPositionLookupTable),
-              mHeaderPolicy(headerPolicy) {}
-
-    void getNextBigram(int *const outBigramPos, int *const outProbability,
-            bool *const outHasNext, int *const bigramEntryPos) const;
-
-    bool skipAllBigrams(int *const pos) const {
-        // Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
-        return true;
-    }
-
-    bool addNewEntry(const int terminalId, const int newTargetTerminalId,
-            const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
-
-    bool removeEntry(const int terminalId, const int targetTerminalId);
-
-    bool updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
-            int *const outBigramCount);
-
-    int getBigramEntryConut(const int terminalId);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4BigramListPolicy);
-
-    int getEntryPosToUpdate(const int targetTerminalIdToFind, const int bigramListPos,
-            int *const outTailEntryPos) const;
-
-    const BigramEntry createUpdatedBigramEntryFrom(const BigramEntry *const originalBigramEntry,
-            const BigramProperty *const bigramProperty) const;
-
-    BigramDictContent *const mBigramDictContent;
-    const TerminalPositionLookupTable *const mTerminalPositionLookupTable;
-    const HeaderPolicy *const mHeaderPolicy;
-};
-} // namespace latinime
-#endif /* LATINIME_VER4_BIGRAM_LIST_POLICY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
deleted file mode 100644
index d7e1952..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h"
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-const int BigramDictContent::INVALID_LINKED_ENTRY_POS = Ver4DictConstants::NOT_A_TERMINAL_ID;
-
-const BigramEntry BigramDictContent::getBigramEntryAndAdvancePosition(
-        int *const bigramEntryPos) const {
-    const BufferWithExtendableBuffer *const bigramListBuffer = getContentBuffer();
-    const int bigramEntryTailPos = (*bigramEntryPos) + getBigramEntrySize();
-    if (*bigramEntryPos < 0 || bigramEntryTailPos > bigramListBuffer->getTailPosition()) {
-        AKLOGE("Invalid bigram entry position. bigramEntryPos: %d, bigramEntryTailPos: %d, "
-                "bufSize: %d", *bigramEntryPos, bigramEntryTailPos,
-                        bigramListBuffer->getTailPosition());
-        ASSERT(false);
-        return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                Ver4DictConstants::NOT_A_TERMINAL_ID);
-    }
-    const int bigramFlags = bigramListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos);
-    const bool isLink = (bigramFlags & Ver4DictConstants::BIGRAM_IS_LINK_MASK) != 0;
-    int probability = NOT_A_PROBABILITY;
-    int timestamp = NOT_A_TIMESTAMP;
-    int level = 0;
-    int count = 0;
-    if (mHasHistoricalInfo) {
-        timestamp = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, bigramEntryPos);
-        level = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, bigramEntryPos);
-        count = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, bigramEntryPos);
-    } else {
-        probability = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::PROBABILITY_SIZE, bigramEntryPos);
-    }
-    const int encodedTargetTerminalId = bigramListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, bigramEntryPos);
-    const int targetTerminalId =
-            (encodedTargetTerminalId == Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID) ?
-                    Ver4DictConstants::NOT_A_TERMINAL_ID : encodedTargetTerminalId;
-    if (isLink) {
-        const int linkedEntryPos = targetTerminalId;
-        if (linkedEntryPos == INVALID_LINKED_ENTRY_POS) {
-            // Bigram list terminator is found.
-            return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                    Ver4DictConstants::NOT_A_TERMINAL_ID);
-        }
-        *bigramEntryPos = linkedEntryPos;
-        return getBigramEntryAndAdvancePosition(bigramEntryPos);
-    }
-    // hasNext is always true because we should continue to read the next entry until the terminator
-    // is found.
-    if (mHasHistoricalInfo) {
-        const HistoricalInfo historicalInfo(timestamp, level, count);
-        return BigramEntry(true /* hasNext */, probability, &historicalInfo, targetTerminalId);
-    } else {
-        return BigramEntry(true /* hasNext */, probability, targetTerminalId);
-    }
-}
-
-bool BigramDictContent::writeBigramEntryAndAdvancePosition(
-        const BigramEntry *const bigramEntryToWrite, int *const entryWritingPos) {
-    return writeBigramEntryAttributesAndAdvancePosition(false /* isLink */,
-            bigramEntryToWrite->getProbability(), bigramEntryToWrite->getTargetTerminalId(),
-            bigramEntryToWrite->getHistoricalInfo()->getTimeStamp(),
-            bigramEntryToWrite->getHistoricalInfo()->getLevel(),
-            bigramEntryToWrite->getHistoricalInfo()->getCount(),
-            entryWritingPos);
-}
-
-bool BigramDictContent::writeBigramEntryAttributesAndAdvancePosition(
-        const bool isLink, const int probability, const int targetTerminalId,
-        const int timestamp, const int level, const int count, int *const entryWritingPos) {
-    BufferWithExtendableBuffer *const bigramListBuffer = getWritableContentBuffer();
-    const int bigramFlags = isLink ? Ver4DictConstants::BIGRAM_IS_LINK_MASK : 0;
-    if (!bigramListBuffer->writeUintAndAdvancePosition(bigramFlags,
-            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, entryWritingPos)) {
-        AKLOGE("Cannot write bigram flags. pos: %d, flags: %x", *entryWritingPos, bigramFlags);
-        return false;
-    }
-    if (mHasHistoricalInfo) {
-        if (!bigramListBuffer->writeUintAndAdvancePosition(timestamp,
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram timestamps. pos: %d, timestamp: %d", *entryWritingPos,
-                    timestamp);
-            return false;
-        }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(level,
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram level. pos: %d, level: %d", *entryWritingPos,
-                    level);
-            return false;
-        }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(count,
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram count. pos: %d, count: %d", *entryWritingPos,
-                    count);
-            return false;
-        }
-    } else {
-        if (!bigramListBuffer->writeUintAndAdvancePosition(probability,
-                Ver4DictConstants::PROBABILITY_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram probability. pos: %d, probability: %d", *entryWritingPos,
-                    probability);
-            return false;
-        }
-    }
-    const int targetTerminalIdToWrite = (targetTerminalId == Ver4DictConstants::NOT_A_TERMINAL_ID) ?
-            Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID : targetTerminalId;
-    if (!bigramListBuffer->writeUintAndAdvancePosition(targetTerminalIdToWrite,
-            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, entryWritingPos)) {
-        AKLOGE("Cannot write bigram target terminal id. pos: %d, target terminal id: %d",
-                *entryWritingPos, targetTerminalId);
-        return false;
-    }
-    return true;
-}
-
-bool BigramDictContent::writeLink(const int linkedEntryPos, const int writingPos) {
-    const int targetTerminalId = linkedEntryPos;
-    int pos = writingPos;
-    return writeBigramEntryAttributesAndAdvancePosition(true /* isLink */,
-            NOT_A_PROBABILITY /* probability */, targetTerminalId, NOT_A_TIMESTAMP, 0 /* level */,
-            0 /* count */, &pos);
-}
-
-bool BigramDictContent::runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const BigramDictContent *const originalBigramDictContent,
-        int *const outBigramEntryCount) {
-    for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
-            it != terminalIdMap->end(); ++it) {
-        const int originalBigramListPos =
-                originalBigramDictContent->getBigramListHeadPos(it->first);
-        if (originalBigramListPos == NOT_A_DICT_POS) {
-            // This terminal does not have a bigram list.
-            continue;
-        }
-        const int bigramListPos = getContentBuffer()->getTailPosition();
-        int bigramEntryCount = 0;
-        // Copy bigram list with GC from original content.
-        if (!runGCBigramList(originalBigramListPos, originalBigramDictContent, bigramListPos,
-                terminalIdMap, &bigramEntryCount)) {
-            AKLOGE("Cannot complete GC for the bigram list. original pos: %d, pos: %d",
-                    originalBigramListPos, bigramListPos);
-            return false;
-        }
-        if (bigramEntryCount == 0) {
-            // All bigram entries are useless. This terminal does not have a bigram list.
-            continue;
-        }
-        *outBigramEntryCount += bigramEntryCount;
-        // Set bigram list position to the lookup table.
-        if (!getUpdatableAddressLookupTable()->set(it->second, bigramListPos)) {
-            AKLOGE("Cannot set bigram list position. terminal id: %d, pos: %d",
-                    it->second, bigramListPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-// Returns whether GC for the bigram list was succeeded or not.
-bool BigramDictContent::runGCBigramList(const int bigramListPos,
-        const BigramDictContent *const sourceBigramDictContent, const int toPos,
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        int *const outEntryCount) {
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    int writingPos = toPos;
-    while (hasNext) {
-        const BigramEntry originalBigramEntry =
-                sourceBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = originalBigramEntry.hasNext();
-        if (!originalBigramEntry.isValid()) {
-            continue;
-        }
-        TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
-                terminalIdMap->find(originalBigramEntry.getTargetTerminalId());
-        if (it == terminalIdMap->end()) {
-            // Target word has been removed.
-            continue;
-        }
-        const BigramEntry updatedBigramEntry =
-                originalBigramEntry.updateTargetTerminalIdAndGetEntry(it->second);
-        if (!writeBigramEntryAndAdvancePosition(&updatedBigramEntry, &writingPos)) {
-            AKLOGE("Cannot write bigram entry to run GC. pos: %d", writingPos);
-            return false;
-        }
-        *outEntryCount += 1;
-    }
-    if (*outEntryCount > 0) {
-        if (!writeTerminator(writingPos)) {
-            AKLOGE("Cannot write terminator to run GC. pos: %d", writingPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h
deleted file mode 100644
index 20bae59..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2013, 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.
- */
-
-#ifndef LATINIME_BIGRAM_DICT_CONTENT_H
-#define LATINIME_BIGRAM_DICT_CONTENT_H
-
-#include <cstdio>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-
-namespace latinime {
-
-class ReadWriteByteArrayView;
-
-class BigramDictContent : public SparseTableDictContent {
- public:
-    BigramDictContent(const ReadWriteByteArrayView *const buffers, const bool hasHistoricalInfo)
-            : SparseTableDictContent(buffers, Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
-              mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    BigramDictContent(const bool hasHistoricalInfo)
-            : SparseTableDictContent(Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
-              mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    int getContentTailPos() const {
-        return getContentBuffer()->getTailPosition();
-    }
-
-    const BigramEntry getBigramEntry(const int bigramEntryPos) const {
-        int readingPos = bigramEntryPos;
-        return getBigramEntryAndAdvancePosition(&readingPos);
-    }
-
-    const BigramEntry getBigramEntryAndAdvancePosition(int *const bigramEntryPos) const;
-
-    // Returns head position of bigram list for a PtNode specified by terminalId.
-    int getBigramListHeadPos(const int terminalId) const {
-        const SparseTable *const addressLookupTable = getAddressLookupTable();
-        if (!addressLookupTable->contains(terminalId)) {
-            return NOT_A_DICT_POS;
-        }
-        return addressLookupTable->get(terminalId);
-    }
-
-    bool writeBigramEntryAtTail(const BigramEntry *const bigramEntryToWrite) {
-        int writingPos = getContentBuffer()->getTailPosition();
-        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
-    }
-
-    bool writeBigramEntry(const BigramEntry *const bigramEntryToWrite, const int entryWritingPos) {
-        int writingPos = entryWritingPos;
-        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
-    }
-
-    bool writeBigramEntryAndAdvancePosition(const BigramEntry *const bigramEntryToWrite,
-            int *const entryWritingPos);
-
-    bool writeTerminator(const int writingPos) {
-        // Terminator is a link to the invalid position.
-        return writeLink(INVALID_LINKED_ENTRY_POS, writingPos);
-    }
-
-    bool writeLink(const int linkedPos, const int writingPos);
-
-    bool createNewBigramList(const int terminalId) {
-        const int bigramListPos = getContentBuffer()->getTailPosition();
-        return getUpdatableAddressLookupTable()->set(terminalId, bigramListPos);
-    }
-
-    bool flushToFile(FILE *const file) const {
-        return flush(file);
-    }
-
-    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            const BigramDictContent *const originalBigramDictContent,
-            int *const outBigramEntryCount);
-
-    int getBigramEntrySize() const {
-        if (mHasHistoricalInfo) {
-            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
-                    + Ver4DictConstants::TIME_STAMP_FIELD_SIZE
-                    + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
-                    + Ver4DictConstants::WORD_COUNT_FIELD_SIZE
-                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-        } else {
-            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
-                    + Ver4DictConstants::PROBABILITY_SIZE
-                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-        }
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(BigramDictContent);
-
-    static const int INVALID_LINKED_ENTRY_POS;
-
-    bool writeBigramEntryAttributesAndAdvancePosition(
-            const bool isLink, const int probability, const int targetTerminalId,
-            const int timestamp, const int level, const int count, int *const entryWritingPos);
-
-    bool runGCBigramList(const int bigramListPos,
-            const BigramDictContent *const sourceBigramDictContent, const int toPos,
-            const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            int *const outEntryCount);
-
-    bool mHasHistoricalInfo;
-};
-} // namespace latinime
-#endif /* LATINIME_BIGRAM_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
deleted file mode 100644
index 2b0cbd9..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2013, 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.
- */
-
-#ifndef LATINIME_BIGRAM_ENTRY_H
-#define LATINIME_BIGRAM_ENTRY_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
-
-namespace latinime {
-
-class BigramEntry {
- public:
-    BigramEntry(const BigramEntry& bigramEntry)
-            : mHasNext(bigramEntry.mHasNext), mProbability(bigramEntry.mProbability),
-              mHistoricalInfo(), mTargetTerminalId(bigramEntry.mTargetTerminalId) {}
-
-    // Entry with historical information.
-    BigramEntry(const bool hasNext, const int probability, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(),
-              mTargetTerminalId(targetTerminalId) {}
-
-    // Entry with historical information.
-    BigramEntry(const bool hasNext, const int probability,
-            const HistoricalInfo *const historicalInfo, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(*historicalInfo),
-              mTargetTerminalId(targetTerminalId) {}
-
-    const BigramEntry getInvalidatedEntry() const {
-        return updateTargetTerminalIdAndGetEntry(Ver4DictConstants::NOT_A_TERMINAL_ID);
-    }
-
-    const BigramEntry updateHasNextAndGetEntry(const bool hasNext) const {
-        return BigramEntry(hasNext, mProbability, &mHistoricalInfo, mTargetTerminalId);
-    }
-
-    const BigramEntry updateTargetTerminalIdAndGetEntry(const int newTargetTerminalId) const {
-        return BigramEntry(mHasNext, mProbability, &mHistoricalInfo, newTargetTerminalId);
-    }
-
-    const BigramEntry updateProbabilityAndGetEntry(const int probability) const {
-        return BigramEntry(mHasNext, probability, &mHistoricalInfo, mTargetTerminalId);
-    }
-
-    const BigramEntry updateHistoricalInfoAndGetEntry(
-            const HistoricalInfo *const historicalInfo) const {
-        return BigramEntry(mHasNext, mProbability, historicalInfo, mTargetTerminalId);
-    }
-
-    bool isValid() const {
-        return mTargetTerminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
-    }
-
-    bool hasNext() const {
-        return mHasNext;
-    }
-
-    int getProbability() const {
-        return mProbability;
-    }
-
-    bool hasHistoricalInfo() const {
-        return mHistoricalInfo.isValid();
-    }
-
-    const HistoricalInfo *getHistoricalInfo() const {
-        return &mHistoricalInfo;
-    }
-
-    int getTargetTerminalId() const {
-        return mTargetTerminalId;
-    }
-
- private:
-    // Copy constructor is public to use this class as a type of return value.
-    DISALLOW_DEFAULT_CONSTRUCTOR(BigramEntry);
-    DISALLOW_ASSIGNMENT_OPERATOR(BigramEntry);
-
-    const bool mHasNext;
-    const int mProbability;
-    const HistoricalInfo mHistoricalInfo;
-    const int mTargetTerminalId;
-};
-} // namespace latinime
-#endif /* LATINIME_BIGRAM_ENTRY_H */
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 ea2d24e..d5749e9 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
@@ -23,6 +23,9 @@
 
 namespace latinime {
 
+const int LanguageModelDictContent::UNIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE = 0;
+const int LanguageModelDictContent::BIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE = 1;
+
 bool LanguageModelDictContent::save(FILE *const file) const {
     return mTrieMap.save(file);
 }
@@ -71,13 +74,22 @@
     return mTrieMap.remove(wordId, bitmapEntryIndex);
 }
 
+LanguageModelDictContent::EntryRange LanguageModelDictContent::getProbabilityEntries(
+        const WordIdArrayView prevWordIds) const {
+    const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
+    return EntryRange(mTrieMap.getEntriesInSpecifiedLevel(bitmapEntryIndex), mHasHistoricalInfo);
+}
+
 bool LanguageModelDictContent::truncateEntries(const int *const entryCounts,
-        const int *const maxEntryCounts, const HeaderPolicy *const headerPolicy) {
+        const int *const maxEntryCounts, const HeaderPolicy *const headerPolicy,
+        int *const outEntryCounts) {
     for (int i = 0; i <= MAX_PREV_WORD_COUNT_FOR_N_GRAM; ++i) {
         if (entryCounts[i] <= maxEntryCounts[i]) {
+            outEntryCounts[i] = entryCounts[i];
             continue;
         }
-        if (!turncateEntriesInSpecifiedLevel(headerPolicy, maxEntryCounts[i], i)) {
+        if (!turncateEntriesInSpecifiedLevel(headerPolicy, maxEntryCounts[i], i,
+                &outEntryCounts[i])) {
             return false;
         }
     }
@@ -179,7 +191,8 @@
 }
 
 bool LanguageModelDictContent::turncateEntriesInSpecifiedLevel(
-        const HeaderPolicy *const headerPolicy, const int maxEntryCount, const int targetLevel) {
+        const HeaderPolicy *const headerPolicy, const int maxEntryCount, const int targetLevel,
+        int *const outEntryCount) {
     std::vector<int> prevWordIds;
     std::vector<EntryInfoToTurncate> entryInfoVector;
     if (!getEntryInfo(headerPolicy, targetLevel, mTrieMap.getRootBitmapEntryIndex(),
@@ -187,8 +200,10 @@
         return false;
     }
     if (static_cast<int>(entryInfoVector.size()) <= maxEntryCount) {
+        *outEntryCount = static_cast<int>(entryInfoVector.size());
         return true;
     }
+    *outEntryCount = maxEntryCount;
     const int entryCountToRemove = static_cast<int>(entryInfoVector.size()) - maxEntryCount;
     std::partial_sort(entryInfoVector.begin(), entryInfoVector.begin() + entryCountToRemove,
             entryInfoVector.end(),
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 43b2aab..aa612e3 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
@@ -39,6 +39,78 @@
  */
 class LanguageModelDictContent {
  public:
+    static const int UNIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE;
+    static const int BIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE;
+
+    // Pair of word id and probability entry used for iteration.
+    class WordIdAndProbabilityEntry {
+     public:
+        WordIdAndProbabilityEntry(const int wordId, const ProbabilityEntry &probabilityEntry)
+                : mWordId(wordId), mProbabilityEntry(probabilityEntry) {}
+
+        int getWordId() const { return mWordId; }
+        const ProbabilityEntry getProbabilityEntry() const { return mProbabilityEntry; }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(WordIdAndProbabilityEntry);
+        DISALLOW_ASSIGNMENT_OPERATOR(WordIdAndProbabilityEntry);
+
+        const int mWordId;
+        const ProbabilityEntry mProbabilityEntry;
+    };
+
+    // Iterator.
+    class EntryIterator {
+     public:
+        EntryIterator(const TrieMap::TrieMapIterator &trieMapIterator,
+                const bool hasHistoricalInfo)
+                : mTrieMapIterator(trieMapIterator), mHasHistoricalInfo(hasHistoricalInfo) {}
+
+        const WordIdAndProbabilityEntry operator*() const {
+            const TrieMap::TrieMapIterator::IterationResult &result = *mTrieMapIterator;
+            return WordIdAndProbabilityEntry(
+                    result.key(), ProbabilityEntry::decode(result.value(), mHasHistoricalInfo));
+        }
+
+        bool operator!=(const EntryIterator &other) const {
+            return mTrieMapIterator != other.mTrieMapIterator;
+        }
+
+        const EntryIterator &operator++() {
+            ++mTrieMapIterator;
+            return *this;
+        }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(EntryIterator);
+        DISALLOW_ASSIGNMENT_OPERATOR(EntryIterator);
+
+        TrieMap::TrieMapIterator mTrieMapIterator;
+        const bool mHasHistoricalInfo;
+    };
+
+    // Class represents range to use range base for loops.
+    class EntryRange {
+     public:
+        EntryRange(const TrieMap::TrieMapRange trieMapRange, const bool hasHistoricalInfo)
+                : mTrieMapRange(trieMapRange), mHasHistoricalInfo(hasHistoricalInfo) {}
+
+        EntryIterator begin() const {
+            return EntryIterator(mTrieMapRange.begin(), mHasHistoricalInfo);
+        }
+
+        EntryIterator end() const {
+            return EntryIterator(mTrieMapRange.end(), mHasHistoricalInfo);
+        }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(EntryRange);
+        DISALLOW_ASSIGNMENT_OPERATOR(EntryRange);
+
+        const TrieMap::TrieMapRange mTrieMapRange;
+        const bool mHasHistoricalInfo;
+    };
+
     LanguageModelDictContent(const ReadWriteByteArrayView trieMapBuffer,
             const bool hasHistoricalInfo)
             : mTrieMap(trieMapBuffer), mHasHistoricalInfo(hasHistoricalInfo) {}
@@ -76,6 +148,8 @@
 
     bool removeNgramProbabilityEntry(const WordIdArrayView prevWordIds, const int wordId);
 
+    EntryRange getProbabilityEntries(const WordIdArrayView prevWordIds) const;
+
     bool updateAllProbabilityEntries(const HeaderPolicy *const headerPolicy,
             int *const outEntryCounts) {
         for (int i = 0; i <= MAX_PREV_WORD_COUNT_FOR_N_GRAM; ++i) {
@@ -87,7 +161,7 @@
 
     // entryCounts should be created by updateAllProbabilityEntries.
     bool truncateEntries(const int *const entryCounts, const int *const maxEntryCounts,
-            const HeaderPolicy *const headerPolicy);
+            const HeaderPolicy *const headerPolicy, int *const outEntryCounts);
 
  private:
     DISALLOW_COPY_AND_ASSIGN(LanguageModelDictContent);
@@ -126,7 +200,7 @@
     bool updateAllProbabilityEntriesInner(const int bitmapEntryIndex, const int level,
             const HeaderPolicy *const headerPolicy, int *const outEntryCounts);
     bool turncateEntriesInSpecifiedLevel(const HeaderPolicy *const headerPolicy,
-            const int maxEntryCount, const int targetLevel);
+            const int maxEntryCount, const int targetLevel, int *const outEntryCount);
     bool getEntryInfo(const HeaderPolicy *const headerPolicy, const int targetLevel,
             const int bitmapEntryIndex, std::vector<int> *const prevWordIds,
             std::vector<EntryInfoToTurncate> *const outEntryInfo) const;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
index 1f40e3d..45f88e9 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
@@ -159,11 +159,6 @@
         AKLOGE("Language model dict content cannot be written.");
         return false;
     }
-    // Write bigram dict content.
-    if (!mBigramDictContent.flushToFile(file)) {
-        AKLOGE("Bigram dict content cannot be written.");
-        return false;
-    }
     // Write shortcut dict content.
     if (!mShortcutDictContent.flushToFile(file)) {
         AKLOGE("Shortcut dict content cannot be written.");
@@ -186,8 +181,6 @@
                   contentBuffers[Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX]),
           mLanguageModelDictContent(contentBuffers[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX],
                   mHeaderPolicy.hasHistoricalInfoOfWords()),
-          mBigramDictContent(&contentBuffers[Ver4DictConstants::BIGRAM_BUFFERS_INDEX],
-                  mHeaderPolicy.hasHistoricalInfoOfWords()),
           mShortcutDictContent(&contentBuffers[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX]),
           mIsUpdatable(mDictBuffer->isUpdatable()) {}
 
@@ -196,7 +189,6 @@
           mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
           mExpandableTrieBuffer(maxTrieSize), mTerminalPositionLookupTable(),
           mLanguageModelDictContent(headerPolicy->hasHistoricalInfoOfWords()),
-          mBigramDictContent(headerPolicy->hasHistoricalInfoOfWords()), mShortcutDictContent(),
-          mIsUpdatable(true) {}
+          mShortcutDictContent(),  mIsUpdatable(true) {}
 
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
index 70a7983..5407525 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
@@ -22,7 +22,6 @@
 
 #include "defines.h"
 #include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h"
 #include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h"
 #include "suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h"
 #include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
@@ -53,7 +52,6 @@
         return mExpandableTrieBuffer.isNearSizeLimit()
                 || mTerminalPositionLookupTable.isNearSizeLimit()
                 || mLanguageModelDictContent.isNearSizeLimit()
-                || mBigramDictContent.isNearSizeLimit()
                 || mShortcutDictContent.isNearSizeLimit();
     }
 
@@ -89,14 +87,6 @@
         return &mLanguageModelDictContent;
     }
 
-    AK_FORCE_INLINE BigramDictContent *getMutableBigramDictContent() {
-        return &mBigramDictContent;
-    }
-
-    AK_FORCE_INLINE const BigramDictContent *getBigramDictContent() const {
-        return &mBigramDictContent;
-    }
-
     AK_FORCE_INLINE ShortcutDictContent *getMutableShortcutDictContent() {
         return &mShortcutDictContent;
     }
@@ -135,7 +125,6 @@
     BufferWithExtendableBuffer mExpandableTrieBuffer;
     TerminalPositionLookupTable mTerminalPositionLookupTable;
     LanguageModelDictContent mLanguageModelDictContent;
-    BigramDictContent mBigramDictContent;
     ShortcutDictContent mShortcutDictContent;
     const int mIsUpdatable;
 };
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 b085a66..9acf2d4 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
@@ -29,20 +29,18 @@
 
 // NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT for Trie and TerminalAddressLookupTable.
 // NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT for language model.
-// NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT for bigram and shortcut.
+// NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT for shortcut.
 const size_t Ver4DictConstants::NUM_OF_CONTENT_BUFFERS_IN_BODY_FILE =
         NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT * 2
                 + NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT
-                + NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT * 2;
+                + NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT;
 const int Ver4DictConstants::TRIE_BUFFER_INDEX = 0;
 const int Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX =
         TRIE_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
 const int Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX =
         TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
-const int Ver4DictConstants::BIGRAM_BUFFERS_INDEX =
-        LANGUAGE_MODEL_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT;
 const int Ver4DictConstants::SHORTCUT_BUFFERS_INDEX =
-        BIGRAM_BUFFERS_INDEX + NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT;
+        LANGUAGE_MODEL_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT;
 
 const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
 const int Ver4DictConstants::PROBABILITY_SIZE = 1;
@@ -56,21 +54,9 @@
 
 const uint8_t Ver4DictConstants::FLAG_REPRESENTS_BEGINNING_OF_SENTENCE = 0x1;
 
-const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16;
-const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE = 4;
 const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
 const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE = 4;
 
-const int Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE = 3;
-// Unsigned int max value of BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE-byte is used for representing
-// invalid terminal ID in bigram lists.
-const int Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID =
-        (1 << (BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE * 8)) - 1;
-const int Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE = 1;
-const int Ver4DictConstants::BIGRAM_PROBABILITY_MASK = 0x0F;
-const int Ver4DictConstants::BIGRAM_IS_LINK_MASK = 0x80;
-const int Ver4DictConstants::BIGRAM_LARGE_PROBABILITY_FIELD_SIZE = 1;
-
 const int Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE = 1;
 const int Ver4DictConstants::SHORTCUT_PROBABILITY_MASK = 0x0F;
 const int Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK = 0x80;
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 230b305..9703531 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
@@ -52,19 +52,9 @@
     // Flags in probability entry.
     static const uint8_t FLAG_REPRESENTS_BEGINNING_OF_SENTENCE;
 
-    static const int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE;
-    static const int BIGRAM_ADDRESS_TABLE_DATA_SIZE;
     static const int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE;
     static const int SHORTCUT_ADDRESS_TABLE_DATA_SIZE;
 
-    static const int BIGRAM_FLAGS_FIELD_SIZE;
-    static const int BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-    static const int INVALID_BIGRAM_TARGET_TERMINAL_ID;
-    static const int BIGRAM_IS_LINK_MASK;
-    static const int BIGRAM_PROBABILITY_MASK;
-    // Used when bigram list has time stamp.
-    static const int BIGRAM_LARGE_PROBABILITY_FIELD_SIZE;
-
     static const int SHORTCUT_FLAGS_FIELD_SIZE;
     static const int SHORTCUT_PROBABILITY_MASK;
     static const int SHORTCUT_HAS_NEXT_MASK;
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 b7c31bf..9ca7124 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
@@ -21,7 +21,6 @@
 #include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
 #include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
 #include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
 #include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h"
 #include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
@@ -230,12 +229,6 @@
     if (!probabilityEntry.isValid() && outAddedNewBigram) {
         *outAddedNewBigram = true;
     }
-    // TODO: Remove.
-    if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, bigramProperty, outAddedNewBigram)) {
-        AKLOGE("Cannot add new bigram entry. prevWordId: %d, wordId: %d",
-                prevWordIds[0], wordId);
-        return false;
-    }
     return true;
 }
 
@@ -244,19 +237,15 @@
     // TODO: Support n-gram.
     LanguageModelDictContent *const languageModelDictContent =
             mBuffers->getMutableLanguageModelDictContent();
-    if (!languageModelDictContent->removeNgramProbabilityEntry(prevWordIds.limit(1 /* maxSize */),
-            wordId)) {
-        // TODO: Uncomment.
-        // return false;
-    }
-    // TODO: Remove.
-    return mBigramPolicy->removeEntry(prevWordIds[0], wordId);
+    return languageModelDictContent->removeNgramProbabilityEntry(prevWordIds.limit(1 /* maxSize */),
+            wordId);
 }
 
+// TODO: Remove when we stop supporting v402 format.
 bool Ver4PatriciaTrieNodeWriter::updateAllBigramEntriesAndDeleteUselessEntries(
             const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) {
-    return mBigramPolicy->updateAllBigramEntriesAndDeleteUselessEntries(
-            sourcePtNodeParams->getTerminalId(), outBigramEntryCount);
+    // Do nothing.
+    return true;
 }
 
 bool Ver4PatriciaTrieNodeWriter::updateAllPositionFields(
@@ -291,12 +280,6 @@
     if (!updateChildrenPosition(toBeUpdatedPtNodeParams, childrenPos)) {
         return false;
     }
-
-    // Counts bigram entries.
-    if (outBigramEntryCount) {
-        *outBigramEntryCount = mBigramPolicy->getBigramEntryConut(
-                toBeUpdatedPtNodeParams->getTerminalId());
-    }
     return true;
 }
 
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 5d73b6e..08b7d38 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
@@ -27,7 +27,6 @@
 
 class BufferWithExtendableBuffer;
 class HeaderPolicy;
-class Ver4BigramListPolicy;
 class Ver4DictBuffers;
 class Ver4PatriciaTrieNodeReader;
 class Ver4PtNodeArrayReader;
@@ -42,10 +41,9 @@
             Ver4DictBuffers *const buffers, const HeaderPolicy *const headerPolicy,
             const PtNodeReader *const ptNodeReader,
             const PtNodeArrayReader *const ptNodeArrayReader,
-            Ver4BigramListPolicy *const bigramPolicy, Ver4ShortcutListPolicy *const shortcutPolicy)
+            Ver4ShortcutListPolicy *const shortcutPolicy)
             : mTrieBuffer(trieBuffer), mBuffers(buffers), mHeaderPolicy(headerPolicy),
-              mReadingHelper(ptNodeReader, ptNodeArrayReader), mBigramPolicy(bigramPolicy),
-              mShortcutPolicy(shortcutPolicy) {}
+              mReadingHelper(ptNodeReader, ptNodeArrayReader), mShortcutPolicy(shortcutPolicy) {}
 
     virtual ~Ver4PatriciaTrieNodeWriter() {}
 
@@ -114,7 +112,6 @@
     Ver4DictBuffers *const mBuffers;
     const HeaderPolicy *const mHeaderPolicy;
     DynamicPtReadingHelper mReadingHelper;
-    Ver4BigramListPolicy *const mBigramPolicy;
     Ver4ShortcutListPolicy *const mShortcutPolicy;
 };
 } // namespace latinime
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 2ea248e..619cdb5 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
@@ -66,8 +66,9 @@
             // Skip PtNodes that represent non-word information.
             continue;
         }
+        const int wordId = isTerminal ? ptNodeParams.getTerminalId() : NOT_A_WORD_ID;
         childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
-                ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
+                ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), wordId,
                 ptNodeParams.hasChildren(),
                 ptNodeParams.isBlacklisted()
                         || ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */,
@@ -93,12 +94,12 @@
     return codePointCount;
 }
 
-int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) const {
+int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const CodePointArrayView wordCodePoints,
+        const bool forceLowerCaseSearch) const {
     DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
     readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    const int ptNodePos =
-            readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch);
+    const int ptNodePos = readingHelper.getTerminalPtNodePositionOfWord(wordCodePoints.data(),
+            wordCodePoints.size(), forceLowerCaseSearch);
     if (readingHelper.isError()) {
         mIsCorrupted = true;
         AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
@@ -158,11 +159,21 @@
     if (!prevWordsPtNodePos) {
         return;
     }
-    const int bigramsPosition = getBigramsPositionOfPtNode(prevWordsPtNodePos[0]);
-    BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
-    while (bigramsIt.hasNext()) {
-        bigramsIt.next();
-        listener->onVisitEntry(bigramsIt.getProbability(), bigramsIt.getBigramPos());
+    // TODO: Support n-gram.
+    const PtNodeParams ptNodeParams =
+            mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(prevWordsPtNodePos[0]);
+    const int prevWordId = ptNodeParams.getTerminalId();
+    const WordIdArrayView prevWordIds = WordIdArrayView::fromObject(&prevWordId);
+    const auto languageModelDictContent = mBuffers->getLanguageModelDictContent();
+    for (const auto entry : languageModelDictContent->getProbabilityEntries(prevWordIds)) {
+        const ProbabilityEntry &probabilityEntry = entry.getProbabilityEntry();
+        const int probability = probabilityEntry.hasHistoricalInfo() ?
+                ForgettingCurveUtils::decodeProbability(
+                        probabilityEntry.getHistoricalInfo(), mHeaderPolicy) :
+                probabilityEntry.getProbability();
+        const int ptNodePos = mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(
+                entry.getWordId());
+        listener->onVisitEntry(probability, ptNodePos);
     }
 }
 
@@ -178,19 +189,7 @@
             ptNodeParams.getTerminalId());
 }
 
-int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_DICT_POS;
-    }
-    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
-    if (ptNodeParams.isDeleted()) {
-        return NOT_A_DICT_POS;
-    }
-    return mBuffers->getBigramDictContent()->getBigramListHeadPos(
-            ptNodeParams.getTerminalId());
-}
-
-bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int length,
+bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePoints,
         const UnigramProperty *const unigramProperty) {
     if (!mBuffers->isUpdatable()) {
         AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
@@ -201,8 +200,9 @@
                 mDictBuffer->getTailPosition());
         return false;
     }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("The word is too long to insert to the dictionary, length: %d", length);
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("The word is too long to insert to the dictionary, length: %zd",
+                wordCodePoints.size());
         return false;
     }
     for (const auto &shortcut : unigramProperty->getShortcuts()) {
@@ -216,8 +216,8 @@
     readingHelper.initWithPtNodeArrayPos(getRootPosition());
     bool addedNewUnigram = false;
     int codePointsToAdd[MAX_WORD_LENGTH];
-    int codePointCountToAdd = length;
-    memmove(codePointsToAdd, word, sizeof(int) * length);
+    int codePointCountToAdd = wordCodePoints.size();
+    memmove(codePointsToAdd, wordCodePoints.data(), sizeof(int) * codePointCountToAdd);
     if (unigramProperty->representsBeginningOfSentence()) {
         codePointCountToAdd = CharUtils::attachBeginningOfSentenceMarker(codePointsToAdd,
                 codePointCountToAdd, MAX_WORD_LENGTH);
@@ -225,14 +225,15 @@
     if (codePointCountToAdd <= 0) {
         return false;
     }
-    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointsToAdd, codePointCountToAdd,
-            unigramProperty, &addedNewUnigram)) {
+    const CodePointArrayView codePointArrayView(codePointsToAdd, codePointCountToAdd);
+    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView.data(),
+            codePointArrayView.size(), unigramProperty, &addedNewUnigram)) {
         if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
             mUnigramCount++;
         }
         if (unigramProperty->getShortcuts().size() > 0) {
             // Add shortcut target.
-            const int wordPos = getTerminalPtNodePositionOfWord(word, length,
+            const int wordPos = getTerminalPtNodePositionOfWord(codePointArrayView,
                     false /* forceLowerCaseSearch */);
             if (wordPos == NOT_A_DICT_POS) {
                 AKLOGE("Cannot find terminal PtNode position to add shortcut target.");
@@ -255,12 +256,12 @@
     }
 }
 
-bool Ver4PatriciaTriePolicy::removeUnigramEntry(const int *const word, const int length) {
+bool Ver4PatriciaTriePolicy::removeUnigramEntry(const CodePointArrayView wordCodePoints) {
     if (!mBuffers->isUpdatable()) {
         AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
         return false;
     }
-    const int ptNodePos = getTerminalPtNodePositionOfWord(word, length,
+    const int ptNodePos = getTerminalPtNodePositionOfWord(wordCodePoints,
             false /* forceLowerCaseSearch */);
     if (ptNodePos == NOT_A_DICT_POS) {
         return false;
@@ -314,7 +315,6 @@
                     false /* isBlacklisted */, MAX_PROBABILITY /* probability */,
                     NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
             if (!addUnigramEntry(prevWordsInfo->getNthPrevWordCodePoints(1 /* n */),
-                    prevWordsInfo->getNthPrevWordCodePointCount(1 /* n */),
                     &beginningOfSentenceUnigramProperty)) {
                 AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
                 return false;
@@ -327,8 +327,8 @@
         }
     }
     const int word1Pos = getTerminalPtNodePositionOfWord(
-            bigramProperty->getTargetCodePoints()->data(),
-            bigramProperty->getTargetCodePoints()->size(), false /* forceLowerCaseSearch */);
+            CodePointArrayView(*bigramProperty->getTargetCodePoints()),
+            false /* forceLowerCaseSearch */);
     if (word1Pos == NOT_A_DICT_POS) {
         return false;
     }
@@ -345,7 +345,7 @@
 }
 
 bool Ver4PatriciaTriePolicy::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const int *const word, const int length) {
+        const CodePointArrayView wordCodePoints) {
     if (!mBuffers->isUpdatable()) {
         AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
         return false;
@@ -359,8 +359,9 @@
         AKLOGE("prev words info is not valid for removing n-gram entry form the dictionary.");
         return false;
     }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %d", length);
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %zd",
+                wordCodePoints.size());
     }
     int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
     prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
@@ -370,7 +371,7 @@
     if (prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
         return false;
     }
-    const int wordPos = getTerminalPtNodePositionOfWord(word, length,
+    const int wordPos = getTerminalPtNodePositionOfWord(wordCodePoints,
             false /* forceLowerCaseSearch */);
     if (wordPos == NOT_A_DICT_POS) {
         return false;
@@ -454,9 +455,9 @@
     }
 }
 
-const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const codePoints,
-        const int codePointCount) const {
-    const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
+const WordProperty Ver4PatriciaTriePolicy::getWordProperty(
+        const CodePointArrayView wordCodePoints) const {
+    const int ptNodePos = getTerminalPtNodePositionOfWord(wordCodePoints,
             false /* forceLowerCaseSearch */);
     if (ptNodePos == NOT_A_DICT_POS) {
         AKLOGE("getWordProperty is called for invalid word.");
@@ -470,41 +471,32 @@
                     ptNodeParams.getTerminalId());
     const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
     // Fetch bigram information.
+    // TODO: Support n-gram.
     std::vector<BigramProperty> bigrams;
-    const int bigramListPos = getBigramsPositionOfPtNode(ptNodePos);
-    if (bigramListPos != NOT_A_DICT_POS) {
-        int bigramWord1CodePoints[MAX_WORD_LENGTH];
-        const BigramDictContent *const bigramDictContent = mBuffers->getBigramDictContent();
-        const TerminalPositionLookupTable *const terminalPositionLookupTable =
-                mBuffers->getTerminalPositionLookupTable();
-        bool hasNext = true;
-        int readingPos = bigramListPos;
-        while (hasNext) {
-            const BigramEntry bigramEntry =
-                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-            hasNext = bigramEntry.hasNext();
-            const int word1TerminalId = bigramEntry.getTargetTerminalId();
-            const int word1TerminalPtNodePos =
-                    terminalPositionLookupTable->getTerminalPtNodePosition(word1TerminalId);
-            if (word1TerminalPtNodePos == NOT_A_DICT_POS) {
-                continue;
-            }
-            // Word (unigram) probability
-            int word1Probability = NOT_A_PROBABILITY;
-            const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
-                    word1TerminalPtNodePos, MAX_WORD_LENGTH, bigramWord1CodePoints,
-                    &word1Probability);
-            const std::vector<int> word1(bigramWord1CodePoints,
-                    bigramWord1CodePoints + codePointCount);
-            const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo();
-            const int probability = bigramEntry.hasHistoricalInfo() ?
-                    ForgettingCurveUtils::decodeProbability(
-                            bigramEntry.getHistoricalInfo(), mHeaderPolicy) :
-                    bigramEntry.getProbability();
-            bigrams.emplace_back(&word1, probability,
-                    historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-                    historicalInfo->getCount());
-        }
+    const int wordId = ptNodeParams.getTerminalId();
+    const WordIdArrayView prevWordIds = WordIdArrayView::fromObject(&wordId);
+    const TerminalPositionLookupTable *const terminalPositionLookupTable =
+            mBuffers->getTerminalPositionLookupTable();
+    int bigramWord1CodePoints[MAX_WORD_LENGTH];
+    for (const auto entry : mBuffers->getLanguageModelDictContent()->getProbabilityEntries(
+            prevWordIds)) {
+        const int word1TerminalPtNodePos =
+                terminalPositionLookupTable->getTerminalPtNodePosition(entry.getWordId());
+        // Word (unigram) probability
+        int word1Probability = NOT_A_PROBABILITY;
+        const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
+                word1TerminalPtNodePos, MAX_WORD_LENGTH, bigramWord1CodePoints,
+                &word1Probability);
+        const std::vector<int> word1(bigramWord1CodePoints,
+                bigramWord1CodePoints + codePointCount);
+        const ProbabilityEntry probabilityEntry = entry.getProbabilityEntry();
+        const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
+        const int probability = probabilityEntry.hasHistoricalInfo() ?
+                ForgettingCurveUtils::decodeProbability(historicalInfo, mHeaderPolicy) :
+                probabilityEntry.getProbability();
+        bigrams.emplace_back(&word1, probability,
+                historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
+                historicalInfo->getCount());
     }
     // Fetch shortcut information.
     std::vector<UnigramProperty::ShortcutProperty> shortcuts;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
index faad429..24f92a4 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -23,7 +23,6 @@
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 #include "suggest/policyimpl/dictionary/header/header_policy.h"
 #include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
 #include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
@@ -31,25 +30,25 @@
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h"
 #include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
 class DicNode;
 class DicNodeVector;
 
+// Word id = Artificial id that is stored in the PtNode looked up by the word.
 class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
  public:
     Ver4PatriciaTriePolicy(Ver4DictBuffers::Ver4DictBuffersPtr buffers)
             : mBuffers(std::move(buffers)), mHeaderPolicy(mBuffers->getHeaderPolicy()),
               mDictBuffer(mBuffers->getWritableTrieBuffer()),
-              mBigramPolicy(mBuffers->getMutableBigramDictContent(),
-                      mBuffers->getTerminalPositionLookupTable(), mHeaderPolicy),
               mShortcutPolicy(mBuffers->getMutableShortcutDictContent(),
                       mBuffers->getTerminalPositionLookupTable()),
               mNodeReader(mDictBuffer, mBuffers->getLanguageModelDictContent(), mHeaderPolicy),
               mPtNodeArrayReader(mDictBuffer),
               mNodeWriter(mDictBuffer, mBuffers.get(), mHeaderPolicy, &mNodeReader,
-                      &mPtNodeArrayReader, &mBigramPolicy, &mShortcutPolicy),
+                      &mPtNodeArrayReader, &mShortcutPolicy),
               mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter),
               mWritingHelper(mBuffers.get()),
               mUnigramCount(mHeaderPolicy->getUnigramCount()),
@@ -67,8 +66,8 @@
             const int terminalPtNodePos, const int maxCodePointCount, int *const outCodePoints,
             int *const outUnigramProbability) const;
 
-    int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const;
+    int getTerminalPtNodePositionOfWord(const CodePointArrayView wordCodePoints,
+            const bool forceLowerCaseSearch) const;
 
     int getProbability(const int unigramProbability, const int bigramProbability) const;
 
@@ -87,16 +86,16 @@
         return &mShortcutPolicy;
     }
 
-    bool addUnigramEntry(const int *const word, const int length,
+    bool addUnigramEntry(const CodePointArrayView wordCodePoints,
             const UnigramProperty *const unigramProperty);
 
-    bool removeUnigramEntry(const int *const word, const int length);
+    bool removeUnigramEntry(const CodePointArrayView wordCodePoints);
 
     bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
             const BigramProperty *const bigramProperty);
 
-    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word1,
-            const int length1);
+    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
+            const CodePointArrayView wordCodePoints);
 
     bool flush(const char *const filePath);
 
@@ -107,8 +106,7 @@
     void getProperty(const char *const query, const int queryLength, char *const outResult,
             const int maxResultLength);
 
-    const WordProperty getWordProperty(const int *const codePoints,
-            const int codePointCount) const;
+    const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const;
 
     int getNextWordAndNextToken(const int token, int *const outCodePoints,
             int *const outCodePointCount);
@@ -132,7 +130,6 @@
     const Ver4DictBuffers::Ver4DictBuffersPtr mBuffers;
     const HeaderPolicy *const mHeaderPolicy;
     BufferWithExtendableBuffer *const mDictBuffer;
-    Ver4BigramListPolicy mBigramPolicy;
     Ver4ShortcutListPolicy mShortcutPolicy;
     Ver4PatriciaTrieNodeReader mNodeReader;
     Ver4PtNodeArrayReader mPtNodeArrayReader;
@@ -143,8 +140,6 @@
     int mBigramCount;
     std::vector<int> mTerminalPtNodePositionsForIteratingWords;
     mutable bool mIsCorrupted;
-
-    int getBigramsPositionOfPtNode(const int ptNodePos) const;
 };
 } // namespace latinime
 #endif // LATINIME_VER4_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
index d53575a..63e43a5 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
@@ -20,7 +20,6 @@
 #include <queue>
 
 #include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
 #include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
@@ -77,13 +76,10 @@
     Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer(),
             mBuffers->getLanguageModelDictContent(), headerPolicy);
     Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer());
-    Ver4BigramListPolicy bigramPolicy(mBuffers->getMutableBigramDictContent(),
-            mBuffers->getTerminalPositionLookupTable(), headerPolicy);
     Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(),
             mBuffers->getTerminalPositionLookupTable());
     Ver4PatriciaTrieNodeWriter ptNodeWriter(mBuffers->getWritableTrieBuffer(),
-            mBuffers, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
-            &shortcutPolicy);
+            mBuffers, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &shortcutPolicy);
 
     int entryCountTable[MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1];
     if (!mBuffers->getMutableLanguageModelDictContent()->updateAllProbabilityEntries(headerPolicy,
@@ -93,14 +89,16 @@
     }
     if (headerPolicy->isDecayingDict()) {
         int maxEntryCountTable[MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1];
-        maxEntryCountTable[0] = headerPolicy->getMaxUnigramCount();
-        maxEntryCountTable[1] = headerPolicy->getMaxBigramCount();
+        maxEntryCountTable[LanguageModelDictContent::UNIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE] =
+                headerPolicy->getMaxUnigramCount();
+        maxEntryCountTable[LanguageModelDictContent::BIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE] =
+                headerPolicy->getMaxBigramCount();
         for (size_t i = 2; i < NELEMS(maxEntryCountTable); ++i) {
             // TODO: Have max n-gram count.
             maxEntryCountTable[i] = headerPolicy->getMaxBigramCount();
         }
         if (!mBuffers->getMutableLanguageModelDictContent()->truncateEntries(entryCountTable,
-                maxEntryCountTable,  headerPolicy)) {
+                maxEntryCountTable, headerPolicy, entryCountTable)) {
             AKLOGE("Failed to truncate entries in language model dict content.");
             return false;
         }
@@ -116,16 +114,6 @@
             &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) {
         return false;
     }
-    const int unigramCount = traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
-            .getValidUnigramCount();
-    const int maxUnigramCount = headerPolicy->getMaxUnigramCount();
-    if (headerPolicy->isDecayingDict() && unigramCount > maxUnigramCount) {
-        if (!truncateUnigrams(&ptNodeReader, &ptNodeWriter, maxUnigramCount)) {
-            AKLOGE("Cannot remove unigrams. current: %d, max: %d", unigramCount,
-                    maxUnigramCount);
-            return false;
-        }
-    }
 
     readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
     DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
@@ -134,21 +122,12 @@
             &traversePolicyToUpdateBigramProbability)) {
         return false;
     }
-    const int bigramCount = traversePolicyToUpdateBigramProbability.getValidBigramEntryCount();
-    const int maxBigramCount = headerPolicy->getMaxBigramCount();
-    if (headerPolicy->isDecayingDict() && bigramCount > maxBigramCount) {
-        if (!truncateBigrams(maxBigramCount)) {
-            AKLOGE("Cannot remove bigrams. current: %d, max: %d", bigramCount, maxBigramCount);
-            return false;
-        }
-    }
 
     // Mapping from positions in mBuffer to positions in bufferToWrite.
     PtNodeWriter::DictPositionRelocationMap dictPositionRelocationMap;
     readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
     Ver4PatriciaTrieNodeWriter ptNodeWriterForNewBuffers(buffersToWrite->getWritableTrieBuffer(),
-            buffersToWrite, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
-            &shortcutPolicy);
+            buffersToWrite, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &shortcutPolicy);
     DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
             traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&ptNodeWriterForNewBuffers,
                     buffersToWrite->getWritableTrieBuffer(), &dictPositionRelocationMap);
@@ -161,12 +140,10 @@
     Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer(),
             buffersToWrite->getLanguageModelDictContent(), headerPolicy);
     Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer());
-    Ver4BigramListPolicy newBigramPolicy(buffersToWrite->getMutableBigramDictContent(),
-            buffersToWrite->getTerminalPositionLookupTable(), headerPolicy);
     Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(),
             buffersToWrite->getTerminalPositionLookupTable());
     Ver4PatriciaTrieNodeWriter newPtNodeWriter(buffersToWrite->getWritableTrieBuffer(),
-            buffersToWrite, headerPolicy, &newPtNodeReader, &newPtNodeArrayreader, &newBigramPolicy,
+            buffersToWrite, headerPolicy, &newPtNodeReader, &newPtNodeArrayreader,
             &newShortcutPolicy);
     // Re-assign terminal IDs for valid terminal PtNodes.
     TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
@@ -179,11 +156,6 @@
             mBuffers->getLanguageModelDictContent(), nullptr /* outNgramCount */)) {
         return false;
     }
-    // Run GC for bigram dict content.
-    if(!buffersToWrite->getMutableBigramDictContent()->runGC(&terminalIdMap,
-            mBuffers->getBigramDictContent(), outBigramCount)) {
-        return false;
-    }
     // Run GC for shortcut dict content.
     if(!buffersToWrite->getMutableShortcutDictContent()->runGC(&terminalIdMap,
             mBuffers->getShortcutDictContent())) {
@@ -204,94 +176,10 @@
             &traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds)) {
         return false;
     }
-    *outUnigramCount = traversePolicyToUpdateAllPositionFields.getUnigramCount();
-    return true;
-}
-
-// TODO: Remove.
-bool Ver4PatriciaTrieWritingHelper::truncateUnigrams(
-        const Ver4PatriciaTrieNodeReader *const ptNodeReader,
-        Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount) {
-    const TerminalPositionLookupTable *const terminalPosLookupTable =
-            mBuffers->getTerminalPositionLookupTable();
-    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
-    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
-            priorityQueue;
-    for (int i = 0; i < nextTerminalId; ++i) {
-        const int terminalPos = terminalPosLookupTable->getTerminalPtNodePosition(i);
-        if (terminalPos == NOT_A_DICT_POS) {
-            continue;
-        }
-        const ProbabilityEntry probabilityEntry =
-                mBuffers->getLanguageModelDictContent()->getProbabilityEntry(i);
-        const int probability = probabilityEntry.hasHistoricalInfo() ?
-                ForgettingCurveUtils::decodeProbability(
-                        probabilityEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
-                probabilityEntry.getProbability();
-        priorityQueue.push(DictProbability(terminalPos, probability,
-                probabilityEntry.getHistoricalInfo()->getTimeStamp()));
-    }
-
-    // Delete unigrams.
-    while (static_cast<int>(priorityQueue.size()) > maxUnigramCount) {
-        const int ptNodePos = priorityQueue.top().getDictPos();
-        priorityQueue.pop();
-        const PtNodeParams ptNodeParams =
-                ptNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-        if (ptNodeParams.representsNonWordInfo()) {
-            continue;
-        }
-        if (!ptNodeWriter->markPtNodeAsWillBecomeNonTerminal(&ptNodeParams)) {
-            AKLOGE("Cannot mark PtNode as willBecomeNonterminal. PtNode pos: %d", ptNodePos);
-            return false;
-        }
-    }
-    return true;
-}
-
-// TODO: Remove.
-bool Ver4PatriciaTrieWritingHelper::truncateBigrams(const int maxBigramCount) {
-    const TerminalPositionLookupTable *const terminalPosLookupTable =
-            mBuffers->getTerminalPositionLookupTable();
-    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
-    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
-            priorityQueue;
-    BigramDictContent *const bigramDictContent = mBuffers->getMutableBigramDictContent();
-    for (int i = 0; i < nextTerminalId; ++i) {
-        const int bigramListPos = bigramDictContent->getBigramListHeadPos(i);
-        if (bigramListPos == NOT_A_DICT_POS) {
-            continue;
-        }
-        bool hasNext = true;
-        int readingPos = bigramListPos;
-        while (hasNext) {
-            const BigramEntry bigramEntry =
-                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-            const int entryPos = readingPos - bigramDictContent->getBigramEntrySize();
-            hasNext = bigramEntry.hasNext();
-            if (!bigramEntry.isValid()) {
-                continue;
-            }
-            const int probability = bigramEntry.hasHistoricalInfo() ?
-                    ForgettingCurveUtils::decodeProbability(
-                            bigramEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
-                    bigramEntry.getProbability();
-            priorityQueue.push(DictProbability(entryPos, probability,
-                    bigramEntry.getHistoricalInfo()->getTimeStamp()));
-        }
-    }
-
-    // Delete bigrams.
-    while (static_cast<int>(priorityQueue.size()) > maxBigramCount) {
-        const int entryPos = priorityQueue.top().getDictPos();
-        const BigramEntry bigramEntry = bigramDictContent->getBigramEntry(entryPos);
-        const BigramEntry invalidatedBigramEntry = bigramEntry.getInvalidatedEntry();
-        if (!bigramDictContent->writeBigramEntry(&invalidatedBigramEntry, entryPos)) {
-            AKLOGE("Cannot write bigram entry to remove. pos: %d", entryPos);
-            return false;
-        }
-        priorityQueue.pop();
-    }
+    *outUnigramCount =
+            entryCountTable[LanguageModelDictContent::UNIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE];
+    *outBigramCount =
+            entryCountTable[LanguageModelDictContent::BIGRAM_COUNT_INDEX_IN_ENTRY_COUNT_TABLE];
     return true;
 }
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
index bb464ad..b6278c4 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
@@ -66,49 +66,6 @@
         const TerminalPositionLookupTable::TerminalIdMap *const mTerminalIdMap;
     };
 
-    // For truncateUnigrams() and truncateBigrams().
-    class DictProbability {
-     public:
-        DictProbability(const int dictPos, const int probability, const int timestamp)
-                : mDictPos(dictPos), mProbability(probability), mTimestamp(timestamp) {}
-
-        int getDictPos() const {
-            return mDictPos;
-        }
-
-        int getProbability() const {
-            return mProbability;
-        }
-
-        int getTimestamp() const {
-            return mTimestamp;
-        }
-
-     private:
-        DISALLOW_DEFAULT_CONSTRUCTOR(DictProbability);
-
-        int mDictPos;
-        int mProbability;
-        int mTimestamp;
-    };
-
-    // For truncateUnigrams() and truncateBigrams().
-    class DictProbabilityComparator {
-     public:
-        bool operator()(const DictProbability &left, const DictProbability &right) {
-            if (left.getProbability() != right.getProbability()) {
-                return left.getProbability() > right.getProbability();
-            }
-            if (left.getTimestamp() != right.getTimestamp()) {
-                return left.getTimestamp() < right.getTimestamp();
-            }
-            return left.getDictPos() > right.getDictPos();
-        }
-
-     private:
-        DISALLOW_ASSIGNMENT_OPERATOR(DictProbabilityComparator);
-    };
-
     bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy,
             Ver4DictBuffers *const buffersToWrite, int *const outUnigramCount,
             int *const outBigramCount);
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 c2aeac2..0076588 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
@@ -98,7 +98,7 @@
         TrieMapIterator(const TrieMap *const trieMap, const int bitmapEntryIndex)
                 : mTrieMap(trieMap), mStateStack(), mBaseBitmapEntryIndex(bitmapEntryIndex),
                   mKey(0), mValue(0), mIsValid(false), mNextLevelBitmapEntryIndex(INVALID_INDEX) {
-            if (!trieMap) {
+            if (!trieMap || mBaseBitmapEntryIndex == INVALID_INDEX) {
                 return;
             }
             const Entry bitmapEntry = mTrieMap->readEntry(mBaseBitmapEntryIndex);
diff --git a/native/jni/src/utils/int_array_view.h b/native/jni/src/utils/int_array_view.h
index 53f2d29..8797b59 100644
--- a/native/jni/src/utils/int_array_view.h
+++ b/native/jni/src/utils/int_array_view.h
@@ -105,6 +105,7 @@
 
 using WordIdArrayView = IntArrayView;
 using PtNodePosArrayView = IntArrayView;
+using CodePointArrayView = IntArrayView;
 
 } // namespace latinime
 #endif // LATINIME_MEMORY_VIEW_H
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
index 3cacba1..ca8d56f 100644
--- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
+++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
@@ -18,6 +18,8 @@
 
 #include <gtest/gtest.h>
 
+#include <unordered_set>
+
 #include "utils/int_array_view.h"
 
 namespace latinime {
@@ -69,5 +71,23 @@
     EXPECT_TRUE(LanguageModelDictContent.removeProbabilityEntry(wordId));
 }
 
+TEST(LanguageModelDictContentTest, TestIterateProbabilityEntry) {
+    LanguageModelDictContent languageModelDictContent(false /* useHistoricalInfo */);
+
+    const ProbabilityEntry originalEntry(0xFC, 100);
+
+    const int wordIds[] = { 1, 2, 3, 4, 5 };
+    for (const int wordId : wordIds) {
+        languageModelDictContent.setProbabilityEntry(wordId, &originalEntry);
+    }
+    std::unordered_set<int> wordIdSet(std::begin(wordIds), std::end(wordIds));
+    for (const auto entry : languageModelDictContent.getProbabilityEntries(WordIdArrayView())) {
+        EXPECT_EQ(originalEntry.getFlags(), entry.getProbabilityEntry().getFlags());
+        EXPECT_EQ(originalEntry.getProbability(), entry.getProbabilityEntry().getProbability());
+        wordIdSet.erase(entry.getWordId());
+    }
+    EXPECT_TRUE(wordIdSet.empty());
+}
+
 }  // namespace
 }  // namespace latinime
diff --git a/native/jni/tests/utils/time_keeper_test.cpp b/native/jni/tests/utils/time_keeper_test.cpp
new file mode 100644
index 0000000..3f54b91
--- /dev/null
+++ b/native/jni/tests/utils/time_keeper_test.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "utils/time_keeper.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace {
+
+TEST(TimeKeeperTest, TestTestMode) {
+    TimeKeeper::setCurrentTime();
+    const int startTime = TimeKeeper::peekCurrentTime();
+    static const int TEST_CURRENT_TIME = 100;
+    TimeKeeper::startTestModeWithForceCurrentTime(TEST_CURRENT_TIME);
+    EXPECT_EQ(TEST_CURRENT_TIME, TimeKeeper::peekCurrentTime());
+    TimeKeeper::setCurrentTime();
+    EXPECT_EQ(TEST_CURRENT_TIME, TimeKeeper::peekCurrentTime());
+    TimeKeeper::stopTestMode();
+    TimeKeeper::setCurrentTime();
+    EXPECT_LE(startTime, TimeKeeper::peekCurrentTime());
+}
+
+}  // namespace
+}  // namespace latinime