Merge "Import translations. DO NOT MERGE"
diff --git a/java/res/values-af/strings-action-keys.xml b/java/res/values-af/strings-action-keys.xml
index bef175b..c7ae3f7 100644
--- a/java/res/values-af/strings-action-keys.xml
+++ b/java/res/values-af/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Vorige"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Klaar"</string>
     <string name="label_send_key" msgid="482252074224462163">"Stuur"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Soek"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Laat wag"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Wag"</string>
 </resources>
diff --git a/java/res/values-am/strings-action-keys.xml b/java/res/values-am/strings-action-keys.xml
index 26e4513..51c2538 100644
--- a/java/res/values-am/strings-action-keys.xml
+++ b/java/res/values-am/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"ቀዳሚ"</string>
     <string name="label_done_key" msgid="7564866296502630852">"ተደርጓል"</string>
     <string name="label_send_key" msgid="482252074224462163">"ላክ"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"ፈልግ"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"ቆም በል"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"ጠብቅ"</string>
 </resources>
diff --git a/java/res/values-ca/strings-action-keys.xml b/java/res/values-ca/strings-action-keys.xml
index 5dcf4a3..2760fb0 100644
--- a/java/res/values-ca/strings-action-keys.xml
+++ b/java/res/values-ca/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Ant."</string>
     <string name="label_done_key" msgid="7564866296502630852">"Fet"</string>
     <string name="label_send_key" msgid="482252074224462163">"Envia"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Cerca"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Atura"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Esp."</string>
 </resources>
diff --git a/java/res/values-en-rGB/strings-action-keys.xml b/java/res/values-en-rGB/strings-action-keys.xml
index b8b02e1..6514e85 100644
--- a/java/res/values-en-rGB/strings-action-keys.xml
+++ b/java/res/values-en-rGB/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Prev"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Finished"</string>
     <string name="label_send_key" msgid="482252074224462163">"Send"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Search"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pause"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Wait"</string>
 </resources>
diff --git a/java/res/values-en-rIN/strings-action-keys.xml b/java/res/values-en-rIN/strings-action-keys.xml
index b8b02e1..6514e85 100644
--- a/java/res/values-en-rIN/strings-action-keys.xml
+++ b/java/res/values-en-rIN/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Prev"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Finished"</string>
     <string name="label_send_key" msgid="482252074224462163">"Send"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Search"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pause"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Wait"</string>
 </resources>
diff --git a/java/res/values-fa/strings-action-keys.xml b/java/res/values-fa/strings-action-keys.xml
index ae393bb..859877c 100644
--- a/java/res/values-fa/strings-action-keys.xml
+++ b/java/res/values-fa/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"قبلی"</string>
     <string name="label_done_key" msgid="7564866296502630852">"اتمام"</string>
     <string name="label_send_key" msgid="482252074224462163">"ارسال"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"جستجو"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"مکث"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"انتظار"</string>
 </resources>
diff --git a/java/res/values-in/strings-action-keys.xml b/java/res/values-in/strings-action-keys.xml
index 052798d..7f1a28e 100644
--- a/java/res/values-in/strings-action-keys.xml
+++ b/java/res/values-in/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Balik"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Beres"</string>
     <string name="label_send_key" msgid="482252074224462163">"Kirim"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Telusur"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Jeda"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Tunggu"</string>
 </resources>
diff --git a/java/res/values-iw/strings-action-keys.xml b/java/res/values-iw/strings-action-keys.xml
index 398c081..f72a6fe 100644
--- a/java/res/values-iw/strings-action-keys.xml
+++ b/java/res/values-iw/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"הקודם"</string>
     <string name="label_done_key" msgid="7564866296502630852">"בוצע"</string>
     <string name="label_send_key" msgid="482252074224462163">"שלח"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"חפש"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"השהה"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"המתן"</string>
 </resources>
diff --git a/java/res/values-ka-rGE/strings-action-keys.xml b/java/res/values-ka-rGE/strings-action-keys.xml
index 3ad6c33..5fa9235 100644
--- a/java/res/values-ka-rGE/strings-action-keys.xml
+++ b/java/res/values-ka-rGE/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"წინა"</string>
     <string name="label_done_key" msgid="7564866296502630852">"დასრ."</string>
     <string name="label_send_key" msgid="482252074224462163">"გაგზ."</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"ძიება"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"პაუზა"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"მოცდა"</string>
 </resources>
diff --git a/java/res/values-km-rKH/strings-action-keys.xml b/java/res/values-km-rKH/strings-action-keys.xml
index d6b11b7..3ff6d49 100644
--- a/java/res/values-km-rKH/strings-action-keys.xml
+++ b/java/res/values-km-rKH/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"មុន"</string>
     <string name="label_done_key" msgid="7564866296502630852">"រួចរាល់"</string>
     <string name="label_send_key" msgid="482252074224462163">"ផ្ញើ"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"ស្វែងរក"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"ផ្អាក"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"រង់ចាំ"</string>
 </resources>
diff --git a/java/res/values-km-rKH/strings-emoji-descriptions.xml b/java/res/values-km-rKH/strings-emoji-descriptions.xml
index 9f1d997..757df50 100644
--- a/java/res/values-km-rKH/strings-emoji-descriptions.xml
+++ b/java/res/values-km-rKH/strings-emoji-descriptions.xml
@@ -25,16 +25,16 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"សញ្ញា​រក្សា​សិទ្ធ"</string>
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"សញ្ញា​រក្សា​សិទ្ធ​"</string>
     <string name="spoken_emoji_00AE" msgid="7708335454134589027">"សញ្ញា​​​ចុះ​បញ្ជី"</string>
     <string name="spoken_emoji_203C" msgid="153340916701508663">"សញ្ញា​ឧទាន​​ពីរ"</string>
-    <string name="spoken_emoji_2049" msgid="4877256448299555371">"សញ្ញា​​ឧទាន​សញ្ញា​សួរ"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"សញ្ញា​​ឧទាន​សញ្ញា​សួរ​​"</string>
     <string name="spoken_emoji_2122" msgid="9188440722954720429">"សញ្ញា​​​និក្ខិត្តសញ្ញា"</string>
     <string name="spoken_emoji_2139" msgid="9114342638917304327">"ប្រភព​ព័ត៌មាន"</string>
     <string name="spoken_emoji_2194" msgid="8055202727034946680">"ព្រួញ​ឆ្វេងស្ដាំ"</string>
     <string name="spoken_emoji_2195" msgid="8028122253301087407">"ព្រួញ​ឡើង​លើ​ចុះក្រោម"</string>
     <string name="spoken_emoji_2196" msgid="4019164898967854363">"ព្រួញ​ទិសពាយព្យ"</string>
-    <string name="spoken_emoji_2197" msgid="4255723717709017801">"ព្រួញ​​ទិស​ឥសាន្ត​ឦសាន្ត"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"ព្រួញ​​ទិស​ឥសាន្ត​ឦសាន្ត​"</string>
     <string name="spoken_emoji_2198" msgid="1452063451313622090">"ព្រួញ​​ទិស​អាគ្នេយ៍"</string>
     <string name="spoken_emoji_2199" msgid="6942722693368807849">"ព្រួញ​​ទិស​និរតី"</string>
     <string name="spoken_emoji_21A9" msgid="5204750172335111188">"ព្រួញ​ទៅ​ឆ្វេង​មាន​ទំពក់"</string>
@@ -45,7 +45,7 @@
     <string name="spoken_emoji_23EA" msgid="2251396938087774944">"ត្រីកោណ​ខ្មៅ​ពីរ​ចង្អុល​ទៅ​ឆ្វេង"</string>
     <string name="spoken_emoji_23EB" msgid="3746885195641491865">"ត្រីកោណ​ខ្មៅ​ពីរ​ចង្អុល​​ឡើង​លើ"</string>
     <string name="spoken_emoji_23EC" msgid="7852372752901163416">"ត្រីកោណ​ខ្មៅ​ពីរ​ចង្អុល​​ចុះក្រោម"</string>
-    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"នាឡិកា​រោទ៍"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"នាឡិកា​រោទ៍​"</string>
     <string name="spoken_emoji_23F3" msgid="166900119581024371">"កែវ​ពិសោធន៍​មាន​ខ្សាច់ហូរ"</string>
     <string name="spoken_emoji_24C2" msgid="3948348737566038470">"អក្សរ​អឹម​ធំ​ក្នុង​រង្វង់"</string>
     <string name="spoken_emoji_25AA" msgid="7865181015100227349">"ការ៉េ​តូច​​ពណ៌ខ្មៅ"</string>
@@ -195,7 +195,7 @@
     <string name="spoken_emoji_1F312" msgid="4458575672576125401">"ព្រះ​ចន្ទ​មួយ​ចំណិត​ស្ដាំ"</string>
     <string name="spoken_emoji_1F313" msgid="7599181787989497294">"ព្រះ​ចន្ទ​ពាក់​កណ្ដាល"</string>
     <string name="spoken_emoji_1F314" msgid="4898293184964365413">"ព្រះ​ចន្ទ​មួយ​ចំណិត​ឆ្វេង"</string>
-    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"ព្រះចន្ទ​ពេញ​វង់"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"ព្រះចន្ទ​ពេញ​វង់​"</string>
     <string name="spoken_emoji_1F316" msgid="2061317145777689569">"ព្រះ​ចន្ទ​ភ្លឺ​មួយ​ចំហៀង"</string>
     <string name="spoken_emoji_1F317" msgid="2721090687319539049">"ព្រះ​ចន្ទ​ភ្លឺ​ពាក់​កណ្ដាល"</string>
     <string name="spoken_emoji_1F318" msgid="3814091755648887570">"ព្រះ​ចន្ទ​ភ្លឺ​មួយ​ចំណិត​ឆ្វេង"</string>
@@ -262,7 +262,7 @@
     <string name="spoken_emoji_1F365" msgid="4963815540953316307">"នំ​ត្រី​រាង​មូល"</string>
     <string name="spoken_emoji_1F366" msgid="7862401745277049404">"ការ៉េម​​បំពង់"</string>
     <string name="spoken_emoji_1F367" msgid="7447972978281980414">"ការ៉េម​កែវ"</string>
-    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ការ៉េម"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ការ៉េម​"</string>
     <string name="spoken_emoji_1F369" msgid="7383712944084857350">"ដូណាត់"</string>
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"ខូគី"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"​​សូកូឡា"</string>
@@ -280,7 +280,7 @@
     <string name="spoken_emoji_1F377" msgid="1762398562314172075">"កែវ​ស្រា"</string>
     <string name="spoken_emoji_1F378" msgid="5528234560590117516">"កែវ​ស្រា​ក្រឡុក"</string>
     <string name="spoken_emoji_1F379" msgid="790581290787943325">"ភេសជ្ជៈ​​​ត្រូពិក"</string>
-    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"កែវ​​ស្រាបៀ"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"កែវ​​ស្រាបៀ​"</string>
     <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"ជល់​កែវ​ស្រាបៀ"</string>
     <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"ដប​ទឹកដោះ​គោ"</string>
     <string name="spoken_emoji_1F380" msgid="3487363857092458827">"ខ្សែ​បូ"</string>
@@ -313,7 +313,7 @@
     <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"កាស"</string>
     <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"ក្ដារ​លាយ​ពណ៌​វិចិត្រករ"</string>
     <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"មួក​​​សម្ដែង​សិល្បៈ"</string>
-    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"តង់​សៀក"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"តង់​សៀក​"</string>
     <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"សំបុត្រ"</string>
     <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"បន្ទះកណ្ដឹង"</string>
     <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"សម្ដែង​សិល្បៈ"</string>
@@ -334,10 +334,10 @@
     <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"និមិត្តសញ្ញា​តន្ត្រី"</string>
     <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"អាវ​កីឡា​​មាន​ខ្សែ​ឆៀង"</string>
     <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"រ៉ាកែត និង​បាល់"</string>
-    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"ជិះ​ស្គី ​និង​ក្ដារ​​ស្គី"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"ជិះ​ស្គី ​និង​ក្ដារ​​ស្គី​"</string>
     <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"បាល់​បោះ​ និង​វណ្ណ​មូល"</string>
     <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"ទង់ជាតិ​ប្រណាំង​ម៉ូតូ"</string>
-    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"អ្នក​ជិះ​​ក្ដារ​រំអិល​លើ​ព្រិល"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"អ្នក​ជិះ​​ក្ដារ​រំអិល​លើ​ព្រិល​"</string>
     <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"អ្នក​រត់"</string>
     <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"អ្នក​ជិះ​ទូក​រអិល​លើ​ទឹក"</string>
     <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ពាន​រង្វាន់"</string>
@@ -354,7 +354,7 @@
     <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"ធនាគារ"</string>
     <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ម៉ាស៊ីន​​អេធីអឹម"</string>
     <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"សណ្ឋាគារ"</string>
-    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"សណ្ឋាគារ​ក្ដី​ស្រឡាញ់"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"សណ្ឋាគារ​ក្ដី​ស្រឡាញ់​"</string>
     <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"ហាង​​ទំនិញ ២៤​ម៉ោង"</string>
     <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"សាលារៀន"</string>
     <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"ហាង​​ទំនិញធំៗ"</string>
@@ -439,12 +439,12 @@
     <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"​មេដៃ​ឡើង​លើ"</string>
     <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"​មេដៃ​ចុះ​ក្រោម"</string>
     <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"ទះ​ដៃ"</string>
-    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"លា​ដៃ"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"លា​ដៃ​"</string>
     <string name="spoken_emoji_1F451" msgid="8257466714629051320">"មកុដ"</string>
     <string name="spoken_emoji_1F452" msgid="4567394011149905466">"មួក​​ស្ត្រី"</string>
     <string name="spoken_emoji_1F453" msgid="5978410551173163010">"វ៉ែនតា"</string>
-    <string name="spoken_emoji_1F454" msgid="348469036193323252">"ក្រ​វ៉ាត់​ករ"</string>
-    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"អាវ​យឺត"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"ក្រ​វ៉ាត់​ករ​"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"អាវ​យឺត​​"</string>
     <string name="spoken_emoji_1F456" msgid="1890991330923356408">"ខោ​ខោវប៊យ"</string>
     <string name="spoken_emoji_1F457" msgid="3904310482655702620">"សំលៀក​បំពាក់"</string>
     <string name="spoken_emoji_1F458" msgid="5704243858031107692">"គី​ម៉ូណូ"</string>
@@ -463,8 +463,8 @@
     <string name="spoken_emoji_1F465" msgid="4461307702499679879">"គណនី"</string>
     <string name="spoken_emoji_1F466" msgid="1938873085514108889">"ក្មេង​​ប្រុស"</string>
     <string name="spoken_emoji_1F467" msgid="8237080594860144998">"ក្មេង​ស្រី"</string>
-    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"បុរស"</string>
-    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"ស្ត្រី"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"បុរស​"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"ស្ត្រី​"</string>
     <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"គ្រួសារ"</string>
     <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"បុរស​​ និង​ស្ត្រី​កាន់ដៃ​គ្នា"</string>
     <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"បុរស​ពីរ​នាក់​កាន់​ដៃ​គ្នា"</string>
@@ -490,16 +490,16 @@
     <string name="spoken_emoji_1F480" msgid="3696253485164878739">"លលាដ៍​ក្បាល"</string>
     <string name="spoken_emoji_1F481" msgid="320408708521966893">"អ្នក​ផ្ដល់​ព័ត៌មាន"</string>
     <string name="spoken_emoji_1F482" msgid="3424354860245608949">"អ្នក​យាម"</string>
-    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"អ្នក​រាំ"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"អ្នក​រាំ​"</string>
     <string name="spoken_emoji_1F484" msgid="7348014979080444885">"ក្រេម​លាប​បបូរ​មាត់"</string>
     <string name="spoken_emoji_1F485" msgid="6133507975565116339">"ថ្នាំ​លាប​​​ក្រចក"</string>
     <string name="spoken_emoji_1F486" msgid="9085459968247394155">"ម៉ាស្សា​មុខ"</string>
     <string name="spoken_emoji_1F487" msgid="1479113637259592150">"កាត់សក់"</string>
     <string name="spoken_emoji_1F488" msgid="6922559285234100252">"ស្លាក​សញ្ញា​កាត់សក់"</string>
     <string name="spoken_emoji_1F489" msgid="8114863680950147305">"ស៊ីរ៉ាំង"</string>
-    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ថ្នាំ​គ្រាប់"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ថ្នាំ​គ្រាប់​"</string>
     <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"ស្នាម​ថើប"</string>
-    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"លិខិត​ស្នេហា"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"លិខិត​ស្នេហា​"</string>
     <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"រោទ៍"</string>
     <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"ត្បូង​ថ្ម"</string>
     <string name="spoken_emoji_1F48F" msgid="741593675183677907">"ថើប"</string>
@@ -525,7 +525,7 @@
     <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"គ្រាប់បែក"</string>
     <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"និមិត្ត​សញ្ញា​​ដេក"</string>
     <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"និមិត្ត​សញ្ញា​​ប៉ះ​ទង្គិច​គ្នា"</string>
-    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"និមិត្ត​សញ្ញា​​ស្រក់​ញើស"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"និមិត្ត​សញ្ញា​​ស្រក់​ញើស​"</string>
     <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"ដំណក់​ទឹក"</string>
     <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"និមិត្ត​សញ្ញា​​ដកឃ្លា"</string>
     <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"គំនរ​ធូលី"</string>
@@ -539,7 +539,7 @@
     <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"ប្ដូរ​​រូបិយប័ណ្ណ"</string>
     <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"សញ្ញា​ដុល្លារ"</string>
     <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"កាត​​ឥណទាន"</string>
-    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​​យ៉េន"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​​យ៉េន​​"</string>
     <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"លុយដុល្លារ"</string>
     <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​អឺរ៉ូ"</string>
     <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​​​ផោន"</string>
@@ -547,7 +547,7 @@
     <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"ក្រាហ្វិក​និន្នាការ​ឡើង​​មាន​​សញ្ញា​យ៉េន"</string>
     <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"កៅអី"</string>
     <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"កុំព្យូទ័រ​ផ្ទាល់ខ្លួន"</string>
-    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"វ៉ា​លី"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"វ៉ា​លី​"</string>
     <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"ឌីស​​តូច"</string>
     <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"ថា​ស​​ទន់"</string>
     <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ថាស"</string>
@@ -557,7 +557,7 @@
     <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"ទំព័រ​​កោង"</string>
     <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"ទំព័រ​បញ្ឈរ"</string>
     <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"ប្រតិទិន"</string>
-    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"ហែក​ប្រតិទិន"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"ហែក​ប្រតិទិន​"</string>
     <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"​កាត​រៀប​តាម​អក្សរ"</string>
     <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"ក្រាហ្វិក​មាន​និន្នាការ​ឡើង"</string>
     <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"ក្រាហ្វិក​មាន​និន្នាការ​ចុះ"</string>
@@ -573,11 +573,11 @@
     <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"សៀវភៅ"</string>
     <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"សៀវភៅ​មាន​ក្រប​ពណ៌"</string>
     <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"សៀវភៅ​​បិទ"</string>
-    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"សៀវភៅ​បើក"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"សៀវភៅ​បើក​​"</string>
     <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"សៀវភៅ​​ពណ៌​បៃតង"</string>
     <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"សៀវភៅ​​ពណ៌​ខៀវ"</string>
     <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"សៀវភៅ​​ពណ៌​ទឹកក្រូច"</string>
-    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"សៀវភៅ"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"សៀវភៅ​"</string>
     <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"ស្លាកឈ្មោះ"</string>
     <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"ក្រដាស​រមូរ"</string>
     <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"កំណត់ចំណាំ"</string>
@@ -589,7 +589,7 @@
     <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"ឧបករណ៍​បំពង​សំឡេង"</string>
     <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"ថា​ស​​​ចេញ"</string>
     <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"ថា​ស​ចូល"</string>
-    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"កញ្ចប់"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"កញ្ចប់​"</string>
     <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"និមិត្ត​សញ្ញា​អ៊ីមែល"</string>
     <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"ស្រោម​​សំបុត្រ​ចូល"</string>
     <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"ស្រោម​សំបុត្រ​​មាន​សញ្ញា​ព្រួញ​ពី​លើ"</string>
@@ -626,7 +626,7 @@
     <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"ដុយ​អគ្គិសនី"</string>
     <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"កែវ​ពង្រីក​ចង្អុល​ខាង​ឆ្វេង"</string>
     <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"កែវ​ពង្រីក​ចង្អុល​ខាង​ស្ដាំ"</string>
-    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"ចាក់សោ​​​ដោយ​ប្រើ​​ប៊ិច"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"ចាក់សោ​​​ដោយ​ប្រើ​​ប៊ិច​"</string>
     <string name="spoken_emoji_1F510" msgid="7658381761691758318">"បិទ​​សោ​ដោយ​ប្រើ​​​​កូនសោ"</string>
     <string name="spoken_emoji_1F511" msgid="262319867774655688">"សោ"</string>
     <string name="spoken_emoji_1F512" msgid="5628688337255115175">"ចាក់សោ"</string>
@@ -645,15 +645,15 @@
     <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"គ្រាប់​ចុច​ ១០"</string>
     <string name="spoken_emoji_1F520" msgid="7335109890337048900">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​អក្សរ​ឡាតាំង​ធំ"</string>
     <string name="spoken_emoji_1F521" msgid="2693185864450925778">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​អក្សរ​ឡាតាំង​តូច"</string>
-    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​​លេខ"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​​លេខ​"</string>
     <string name="spoken_emoji_1F523" msgid="3318053476401719421">"ការ​បញ្ចូល​និមិត្តសញ្ញា"</string>
     <string name="spoken_emoji_1F524" msgid="1625073997522316331">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​អក្សរ​ឡាតាំង"</string>
     <string name="spoken_emoji_1F525" msgid="4083884189172963790">"ភ្លើង"</string>
     <string name="spoken_emoji_1F526" msgid="2035494936742643580">"ពិល​​អគ្គិសនី"</string>
     <string name="spoken_emoji_1F527" msgid="134257142354034271">"ម៉ាឡេត"</string>
     <string name="spoken_emoji_1F528" msgid="700627429570609375">"ញញួរ"</string>
-    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"ឡោ​ស៊ី"</string>
-    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"កាំបិត"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"ឡោ​ស៊ី​​"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"កាំបិត​​"</string>
     <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"កាំភ្លើង​ខ្លី"</string>
     <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"មីក្រូទស្សន៍"</string>
     <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"កែវ​យឹត"</string>
@@ -662,7 +662,7 @@
     <string name="spoken_emoji_1F530" msgid="3572898444281774023">"និមិត្តសញ្ញា​ជប៉ុន​សម្រាប់​អ្នក​ចាប់ផ្ដើម"</string>
     <string name="spoken_emoji_1F531" msgid="5225633376450025396">"លំពែង​មុខ​បី"</string>
     <string name="spoken_emoji_1F532" msgid="9169568490485180779">"ប៊ូតុង​ការេ​ពណ៌​ខ្មៅ"</string>
-    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"ប៊ូតុង​ការ៉េ​ពណ៌​ស"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"ប៊ូតុង​ការ៉េ​ពណ៌​ស​"</string>
     <string name="spoken_emoji_1F534" msgid="8339298801331865340">"រង្វង់​ពណ៌​ក្រហម​​​ធំ"</string>
     <string name="spoken_emoji_1F535" msgid="1227403104835533512">"រង្វង់​ពណ៌​ខៀវ​ធំ"</string>
     <string name="spoken_emoji_1F536" msgid="5477372445510469331">"ពេជ្រ​ពណ៌​ទឹកក្រូច​ធំ"</string>
@@ -745,8 +745,8 @@
     <string name="spoken_emoji_1F628" msgid="8875777401624904224">"មុខ​ភ័យ​ខ្លាច"</string>
     <string name="spoken_emoji_1F629" msgid="1411538490319190118">"មុខ​​នឿយហត់"</string>
     <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"មុខ​​ងងុយ​គេង"</string>
-    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"មុខ​អស់កម្លាំង"</string>
-    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"មុខ​ក្រញេវក្រញូវ"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"មុខ​អស់កម្លាំង​​"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"មុខ​ក្រញេវក្រញូវ​"</string>
     <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"មុខ​យំ​លឺៗ"</string>
     <string name="spoken_emoji_1F62E" msgid="726083405284353894">"មុខ​បើក​មាត់"</string>
     <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"មុខ​ស្ងៀមស្ងាត់"</string>
@@ -784,7 +784,7 @@
     <string name="spoken_emoji_1F683" msgid="8772750354339223092">"ទូរ​​រថភ្លើង"</string>
     <string name="spoken_emoji_1F684" msgid="346396777356203608">"រថភ្លើង​ល្បឿន​លឿន"</string>
     <string name="spoken_emoji_1F685" msgid="1237059817190832730">"រថភ្លើង​ល្បឿន​លឿន​​មាន​ច្រមុះ"</string>
-    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"រថភ្លើង"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"រថភ្លើង​"</string>
     <string name="spoken_emoji_1F687" msgid="5110143437960392837">"មេត្រូ"</string>
     <string name="spoken_emoji_1F688" msgid="4702085029871797965">"រថភ្លើង​ប្រើ​​​ពន្លឺ"</string>
     <string name="spoken_emoji_1F689" msgid="2375851019798817094">"ស្ថានីយ"</string>
@@ -803,7 +803,7 @@
     <string name="spoken_emoji_1F696" msgid="6391604457418285404">"តាក់ស៊ី​ខាង​មុខ"</string>
     <string name="spoken_emoji_1F697" msgid="7978399334396733790">"រថយន្ត"</string>
     <string name="spoken_emoji_1F698" msgid="7006050861129732018">"រថយន្ត​ខាង​មុខ"</string>
-    <string name="spoken_emoji_1F699" msgid="630317052666590607">"រថយន្ត​​​សម្រាប់​កម្សាន្ត"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"រថយន្ត​​​សម្រាប់​កម្សាន្ត​"</string>
     <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"រថយន្ត​​ចែក​ចាយ"</string>
     <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"ឡាន​កាមីយ៉ុង"</string>
     <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ត្រាក់ទ័រ"</string>
@@ -819,7 +819,7 @@
     <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"ភ្លើង​ចរាចរណ៍​បញ្ឈរ"</string>
     <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"សញ្ញា​​សំណង់"</string>
     <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"រថយន្ត​​ប៉ូលិស​បើក​សារ៉ែន​វិល"</string>
-    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"បង្គោល​ទង់ជាតិ​រាង​ត្រីកោណ"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"បង្គោល​ទង់ជាតិ​រាង​ត្រីកោណ​"</string>
     <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"ទ្វារ"</string>
     <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"សញ្ញា​ហាម​ចូល"</string>
     <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"​សញ្ញា​ជក់​បារី"</string>
diff --git a/java/res/values-lo-rLA/strings-action-keys.xml b/java/res/values-lo-rLA/strings-action-keys.xml
index 2399305..e1cd913 100644
--- a/java/res/values-lo-rLA/strings-action-keys.xml
+++ b/java/res/values-lo-rLA/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"ກ່ອນໜ້າ"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Done"</string>
     <string name="label_send_key" msgid="482252074224462163">"ສົ່ງ"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"ຊອກຫາ"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"ຢຸດຊົ່ວຄາວ"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"ລໍຖ້າ"</string>
 </resources>
diff --git a/java/res/values-lo-rLA/strings-emoji-descriptions.xml b/java/res/values-lo-rLA/strings-emoji-descriptions.xml
index 83a702e..0747fa6 100644
--- a/java/res/values-lo-rLA/strings-emoji-descriptions.xml
+++ b/java/res/values-lo-rLA/strings-emoji-descriptions.xml
@@ -210,7 +210,7 @@
     <string name="spoken_emoji_1F330" msgid="3115760035618051575">"​ລູກ​ເກົາ​ລັດ"</string>
     <string name="spoken_emoji_1F331" msgid="5658888205290008691">"​ກ້າ​ໄມ້"</string>
     <string name="spoken_emoji_1F332" msgid="2935650450421165938">"ຕົ້ນ​ໄມ້​ບໍ່​ຜັດ​ໃບ"</string>
-    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"​ຕົ້ນ​ໄມ້​ຜັດໃບ"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"​ຕົ້ນ​ໄມ້​ຜັດໃບ​"</string>
     <string name="spoken_emoji_1F334" msgid="6183375224678417894">"​ຕົ້ນ​ປາມ"</string>
     <string name="spoken_emoji_1F335" msgid="5352418412103584941">"​ກະ​ບອງ​ເພັດ"</string>
     <string name="spoken_emoji_1F337" msgid="3839107352363566289">"​ທິວ​ລິບ"</string>
@@ -450,7 +450,7 @@
     <string name="spoken_emoji_1F458" msgid="5704243858031107692">"​ກິ​ໂມ​ໂນ"</string>
     <string name="spoken_emoji_1F459" msgid="3553148747050035251">"​ບິ​ກີ​ນີ"</string>
     <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"​ເສື້ອ​ຜ້າ​ຜູ່​ຍິງ"</string>
-    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"ກະ​ເປົາ"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"ກະ​ເປົາ​"</string>
     <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"ກະ​ເປົາ"</string>
     <string name="spoken_emoji_1F45D" msgid="812176504300064819">"​ກະ​ເປົາ"</string>
     <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"​ເກີບ​ຜູ່​ຊາຍ"</string>
diff --git a/java/res/values-mn-rMN/strings-action-keys.xml b/java/res/values-mn-rMN/strings-action-keys.xml
index a855386..8ebb5bb 100644
--- a/java/res/values-mn-rMN/strings-action-keys.xml
+++ b/java/res/values-mn-rMN/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Өмнөх"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Дууссан"</string>
     <string name="label_send_key" msgid="482252074224462163">"Илгээх"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Хайлт"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Түр зогсоох"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Хүлээх"</string>
 </resources>
diff --git a/java/res/values-pt-rPT/strings-action-keys.xml b/java/res/values-pt-rPT/strings-action-keys.xml
index 1b5921f..73a6c49 100644
--- a/java/res/values-pt-rPT/strings-action-keys.xml
+++ b/java/res/values-pt-rPT/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Ant."</string>
     <string name="label_done_key" msgid="7564866296502630852">"Conc."</string>
     <string name="label_send_key" msgid="482252074224462163">"Env."</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Pesquisar"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pausa"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Esp."</string>
 </resources>
diff --git a/java/res/values-ro/strings-action-keys.xml b/java/res/values-ro/strings-action-keys.xml
index bee4b12..1a15415 100644
--- a/java/res/values-ro/strings-action-keys.xml
+++ b/java/res/values-ro/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Înap."</string>
     <string name="label_done_key" msgid="7564866296502630852">"Gata"</string>
     <string name="label_send_key" msgid="482252074224462163">"Trim."</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Căutați"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pauză"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Așt."</string>
 </resources>
diff --git a/java/res/values-sk/strings-action-keys.xml b/java/res/values-sk/strings-action-keys.xml
index ffc5be2..84e1c31 100644
--- a/java/res/values-sk/strings-action-keys.xml
+++ b/java/res/values-sk/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Pred."</string>
     <string name="label_done_key" msgid="7564866296502630852">"OK"</string>
     <string name="label_send_key" msgid="482252074224462163">"Posl."</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Hľadať"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pauza"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Čakať"</string>
 </resources>
diff --git a/java/res/values-uk/strings-action-keys.xml b/java/res/values-uk/strings-action-keys.xml
index 8b71498..206fcf0 100644
--- a/java/res/values-uk/strings-action-keys.xml
+++ b/java/res/values-uk/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Назад"</string>
     <string name="label_done_key" msgid="7564866296502630852">"ОК"</string>
     <string name="label_send_key" msgid="482252074224462163">"Слати"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Пошук"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Пауза"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Ждати"</string>
 </resources>
diff --git a/java/res/values-vi/strings-action-keys.xml b/java/res/values-vi/strings-action-keys.xml
index 16b7c95..3c40608 100644
--- a/java/res/values-vi/strings-action-keys.xml
+++ b/java/res/values-vi/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Trước"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Xong"</string>
     <string name="label_send_key" msgid="482252074224462163">"Gửi"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Tìm kiếm"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Tdừng"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Đợi"</string>
 </resources>
diff --git a/java/res/values-zu/strings-action-keys.xml b/java/res/values-zu/strings-action-keys.xml
index 5d60a6c..fe36678 100644
--- a/java/res/values-zu/strings-action-keys.xml
+++ b/java/res/values-zu/strings-action-keys.xml
@@ -25,8 +25,7 @@
     <string name="label_previous_key" msgid="1421141755779895275">"Okwedlule"</string>
     <string name="label_done_key" msgid="7564866296502630852">"Kwenziwe"</string>
     <string name="label_send_key" msgid="482252074224462163">"Thumela"</string>
-    <!-- no translation found for label_search_key (7965186050435796642) -->
-    <skip />
+    <string name="label_search_key" msgid="7965186050435796642">"Sesha"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Misa isikhashana"</string>
     <string name="label_wait_key" msgid="5891247853595466039">"Linda"</string>
 </resources>
diff --git a/java/res/values/keyboard-themes.xml b/java/res/values/keyboard-themes.xml
index a06082c..28a34c3 100644
--- a/java/res/values/keyboard-themes.xml
+++ b/java/res/values/keyboard-themes.xml
@@ -20,13 +20,14 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- For keyboard color scheme option dialog. -->
     <string-array name="keyboard_theme_names" translatable="false">
-        <!-- TODO: Make this item as translatable string resource. -->
-        <item>Material</item>
-        <item>@string/keyboard_color_scheme_white</item>
-        <item>@string/keyboard_color_scheme_blue</item>
+        <!-- TODO: Implement Material Light theme. -->
+        <item>@string/keyboard_theme_material_dark</item>
+        <item>@string/keyboard_theme_holo_white</item>
+        <item>@string/keyboard_theme_holo_blue</item>
     </string-array>
     <!-- An element must be a keyboard theme id of {@link KeyboardTheme#THEME_ID_*}. -->
     <string-array name="keyboard_theme_ids" translatable="false">
+        <!-- TODO: Implement Material Light theme. -->
         <item>3</item>
         <item>2</item>
         <item>0</item>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 8849115..9ec3f46 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -36,22 +36,18 @@
     <!-- Option to control whether or not to show a popup with a larger font on each key press. -->
     <string name="popup_on_keypress">Popup on keypress</string>
 
-    <!-- Category title for general settings for Android keyboard -->
-    <string name="general_category">General</string>
-
-    <!-- Category title for text prediction -->
-    <string name="correction_category">Text correction</string>
-
-    <!-- Category title for gesture typing -->
-    <string name="gesture_typing_category">Gesture typing</string>
-
-    <!-- Category title for misc options  -->
-    <string name="misc_category">Other options</string>
-
-    <!-- Option name for advanced settings screen [CHAR LIMIT=25] -->
-    <string name="advanced_settings">Advanced settings</string>
-    <!-- Option summary for advanced settings screen [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] -->
-    <string name="advanced_settings_summary">Options for experts</string>
+    <!-- Settings screen title for input preferences [CHAR LIMIT=25]-->
+    <string name="settings_screen_input">Input preferences</string>
+    <!-- Settings screen title for appearance preferences [CHAR LIMIT=25] -->
+    <string name="settings_screen_appearances">Appearance</string>
+    <!-- Settings screen title for multi lingual options [CHAR_LIMIT=25] -->
+    <string name="settings_screen_multi_lingual">Multi lingual options</string>
+    <!-- Settings screen title for gesture typing preferences [CHAR_LIMIT=25] -->
+    <string name="settings_screen_gesture">Gesture typing preferences</string>
+    <!-- Settings screen title for text correction options [CHAR_LIMIT=25] -->
+    <string name="settings_screen_correction">Text correction</string>
+    <!-- Settings screen title for advanced settings [CHAR LIMIT=25] -->
+    <string name="settings_screen_advanced">Advanced</string>
 
     <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
     <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
@@ -295,12 +291,16 @@
     <!-- Description for Emoji keyboard subtype [CHAR LIMIT=25] -->
     <string name="subtype_emoji">Emoji</string>
 
-    <!-- Title of the preference settings for switching keyboard color scheme [CHAR LIMIT=35] -->
-    <string name="keyboard_color_scheme">Color scheme</string>
-    <!-- The keyboard color scheme name, White [CHAR LIMIT=16] -->
-    <string name="keyboard_color_scheme_white">White</string>
-    <!-- The keyboard color scheme name, Blue [CHAR LIMIT=16] -->
-    <string name="keyboard_color_scheme_blue">Blue</string>
+    <!-- Title of the preference settings for switching keyboard theme [CHAR LIMIT=35] -->
+    <string name="keyboard_theme">Keyboard theme</string>
+    <!-- The keyboard theme name, Holo White [CHAR LIMIT=25] -->
+    <string name="keyboard_theme_holo_white">Holo White</string>
+    <!-- The keyboard theme name, Holo Blue [CHAR LIMIT=25] -->
+    <string name="keyboard_theme_holo_blue">Holo Blue</string>
+    <!-- The keyboard theme name, Material Dark [CHAR LIMIT=25] -->
+    <string name="keyboard_theme_material_dark">Material Dark</string>
+    <!-- The keyboard theme name, Material Light [CHAR LIMIT=25] -->
+    <string name="keyboard_theme_material_light">Material Light</string>
 
     <!-- Title of the preference settings for custom input styles (language and keyboard layout pairs) [CHAR LIMIT=35]-->
     <string name="custom_input_styles_title">Custom input styles</string>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 0e9c161..e71d951 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -18,15 +18,21 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     android:key="english_ime_settings">
-    <PreferenceCategory
-        android:title="@string/general_category"
-        android:key="general_settings">
+    <PreferenceScreen
+        android:title="@string/settings_screen_input"
+        android:key="screen_input">
         <CheckBoxPreference
             android:key="auto_cap"
             android:title="@string/auto_cap"
             android:summary="@string/auto_cap_summary"
-            android:persistent="true"
-            android:defaultValue="true" />
+            android:defaultValue="true"
+            android:persistent="true" />
+        <CheckBoxPreference
+            android:key="pref_key_use_double_space_period"
+            android:title="@string/use_double_space_period"
+            android:summary="@string/use_double_space_period_summary"
+            android:defaultValue="true"
+            android:persistent="true" />
         <CheckBoxPreference
             android:key="vibrate_on"
             android:title="@string/vibrate_on_keypress"
@@ -40,17 +46,67 @@
         <CheckBoxPreference
             android:key="popup_on"
             android:title="@string/popup_on_keypress"
-            android:persistent="true"
-            android:defaultValue="@bool/config_default_key_preview_popup" />
+            android:defaultValue="@bool/config_default_key_preview_popup"
+            android:persistent="true" />
         <CheckBoxPreference
             android:key="pref_voice_input_key"
             android:title="@string/voice_input"
-            android:persistent="true"
-            android:defaultValue="true" />
-    </PreferenceCategory>
-    <PreferenceCategory
-        android:title="@string/correction_category"
-        android:key="correction_settings">
+            android:defaultValue="true"
+            android:persistent="true" />
+    </PreferenceScreen>
+    <ListPreference
+        android:key="pref_keyboard_theme"
+        android:title="@string/keyboard_theme"
+        android:entryValues="@array/keyboard_theme_ids"
+        android:entries="@array/keyboard_theme_names"
+        android:persistent="true" />
+    <PreferenceScreen
+        android:title="@string/settings_screen_multi_lingual"
+        android:key="screen_multi_lingual">
+        <CheckBoxPreference
+            android:key="pref_show_language_switch_key"
+            android:title="@string/show_language_switch_key"
+            android:summary="@string/show_language_switch_key_summary"
+            android:defaultValue="true"
+            android:persistent="true" />
+        <CheckBoxPreference
+            android:key="pref_include_other_imes_in_language_switch_list"
+            android:dependency="pref_show_language_switch_key"
+            android:title="@string/include_other_imes_in_language_switch_list"
+            android:summary="@string/include_other_imes_in_language_switch_list_summary"
+            android:defaultValue="false"
+            android:persistent="true" />
+        <PreferenceScreen
+            android:fragment="com.android.inputmethod.latin.settings.AdditionalSubtypeSettings"
+            android:key="custom_input_styles"
+            android:title="@string/custom_input_styles_title" />
+    </PreferenceScreen>
+    <PreferenceScreen
+        android:title="@string/settings_screen_gesture"
+        android:key="screen_gesture">
+        <CheckBoxPreference
+            android:key="gesture_input"
+            android:title="@string/gesture_input"
+            android:summary="@string/gesture_input_summary"
+            android:defaultValue="true"
+            android:persistent="true" />
+        <CheckBoxPreference
+            android:key="pref_gesture_floating_preview_text"
+            android:dependency="gesture_input"
+            android:title="@string/gesture_floating_preview_text"
+            android:summary="@string/gesture_floating_preview_text_summary"
+            android:defaultValue="true"
+            android:persistent="true" />
+        <CheckBoxPreference
+            android:key="pref_gesture_preview_trail"
+            android:dependency="gesture_input"
+            android:title="@string/gesture_preview_trail"
+            android:defaultValue="true"
+            android:persistent="true" />
+    </PreferenceScreen>
+    <PreferenceScreen
+        android:title="@string/settings_screen_correction"
+        android:key="screen_correction">
         <PreferenceScreen
             android:key="edit_personal_dictionary"
             android:title="@string/edit_personal_dictionary">
@@ -71,137 +127,74 @@
             android:key="pref_key_block_potentially_offensive"
             android:title="@string/prefs_block_potentially_offensive_title"
             android:summary="@string/prefs_block_potentially_offensive_summary"
-            android:persistent="true"
-            android:defaultValue="@bool/config_block_potentially_offensive" />
+            android:defaultValue="@bool/config_block_potentially_offensive"
+            android:persistent="true" />
         <ListPreference
             android:key="auto_correction_threshold"
             android:title="@string/auto_correction"
             android:summary="@string/auto_correction_summary"
-            android:persistent="true"
             android:entryValues="@array/auto_correction_threshold_mode_indexes"
             android:entries="@array/auto_correction_threshold_modes"
-            android:defaultValue="@string/auto_correction_threshold_mode_index_modest" />
+            android:defaultValue="@string/auto_correction_threshold_mode_index_modest"
+            android:persistent="true" />
         <ListPreference
             android:key="show_suggestions_setting"
             android:summary="@string/prefs_show_suggestions_summary"
             android:title="@string/prefs_show_suggestions"
-            android:persistent="true"
             android:entryValues="@array/prefs_suggestion_visibility_values"
             android:entries="@array/prefs_suggestion_visibilities"
-            android:defaultValue="@string/prefs_suggestion_visibility_default_value" />
+            android:defaultValue="@string/prefs_suggestion_visibility_default_value"
+            android:persistent="true" />
         <CheckBoxPreference
             android:key="pref_key_use_personalized_dicts"
             android:title="@string/use_personalized_dicts"
             android:summary="@string/use_personalized_dicts_summary"
-            android:persistent="true"
-            android:defaultValue="true" />
-        <!-- title will be set programmatically to embed application name -->
+            android:defaultValue="true"
+            android:persistent="true" />
         <CheckBoxPreference
-            android:key="pref_enable_metrics_logging"
-            android:summary="@string/enable_metrics_logging_summary"
-            android:persistent="true"
-            android:defaultValue="true" />
-    </PreferenceCategory>
-    <PreferenceCategory
-        android:title="@string/gesture_typing_category"
-        android:key="gesture_typing_settings">
-        <CheckBoxPreference
-            android:key="gesture_input"
-            android:title="@string/gesture_input"
-            android:summary="@string/gesture_input_summary"
-            android:persistent="true"
-            android:defaultValue="true" />
-        <!-- TODO: Move these two options to the advanced settings. -->
-        <CheckBoxPreference
-            android:key="pref_gesture_floating_preview_text"
-            android:dependency="gesture_input"
-            android:title="@string/gesture_floating_preview_text"
-            android:summary="@string/gesture_floating_preview_text_summary"
-            android:persistent="true"
-            android:defaultValue="true" />
-        <CheckBoxPreference
-            android:key="pref_gesture_preview_trail"
-            android:dependency="gesture_input"
-            android:title="@string/gesture_preview_trail"
-            android:persistent="true"
-            android:defaultValue="true" />
-    </PreferenceCategory>
-    <PreferenceCategory
-        android:title="@string/misc_category"
-        android:key="misc_settings">
+            android:key="pref_key_use_contacts_dict"
+            android:title="@string/use_contacts_dict"
+            android:summary="@string/use_contacts_dict_summary"
+            android:defaultValue="true"
+            android:persistent="true" />
         <CheckBoxPreference
             android:key="next_word_prediction"
             android:title="@string/bigram_prediction"
             android:summary="@string/bigram_prediction_summary"
-            android:persistent="true"
-            android:defaultValue="true" />
-        <PreferenceScreen
-            android:key="pref_advanced_settings"
-            android:title="@string/advanced_settings"
-            android:summary="@string/advanced_settings_summary">
-            <CheckBoxPreference
-                android:key="pref_key_use_contacts_dict"
-                android:title="@string/use_contacts_dict"
-                android:summary="@string/use_contacts_dict_summary"
-                android:persistent="true"
-                android:defaultValue="true" />
-            <CheckBoxPreference
-                android:key="pref_key_use_double_space_period"
-                android:title="@string/use_double_space_period"
-                android:summary="@string/use_double_space_period_summary"
-                android:persistent="true"
-                android:defaultValue="true" />
-            <CheckBoxPreference
-                android:key="pref_show_language_switch_key"
-                android:title="@string/show_language_switch_key"
-                android:summary="@string/show_language_switch_key_summary"
-                android:persistent="true"
-                android:defaultValue="true" />
-            <CheckBoxPreference
-                android:key="pref_include_other_imes_in_language_switch_list"
-                android:dependency="pref_show_language_switch_key"
-                android:title="@string/include_other_imes_in_language_switch_list"
-                android:summary="@string/include_other_imes_in_language_switch_list_summary"
-                android:persistent="true"
-                android:defaultValue="false" />
-            <ListPreference
-                android:key="pref_keyboard_theme"
-                android:title="@string/keyboard_color_scheme"
-                android:persistent="true"
-                android:entryValues="@array/keyboard_theme_ids"
-                android:entries="@array/keyboard_theme_names" />
-            <PreferenceScreen
-                android:fragment="com.android.inputmethod.latin.settings.AdditionalSubtypeSettings"
-                android:key="custom_input_styles"
-                android:title="@string/custom_input_styles_title" />
-            <!-- TODO: consolidate key preview dismiss delay with the key preview animation parameters. -->
-            <ListPreference
-                android:key="pref_key_preview_popup_dismiss_delay"
-                android:title="@string/key_preview_popup_dismiss_delay" />
-            <com.android.inputmethod.latin.settings.SeekBarDialogPreference
-                android:key="pref_vibration_duration_settings"
-                android:title="@string/prefs_keypress_vibration_duration_settings"
-                latin:maxValue="@integer/config_max_vibration_duration" />
-            <com.android.inputmethod.latin.settings.SeekBarDialogPreference
-                android:key="pref_keypress_sound_volume"
-                android:title="@string/prefs_keypress_sound_volume_settings"
-                latin:maxValue="100" /> <!-- percent -->
-            <!-- The settigs for showing setup wizard application icon shouldn't be persistent and
-                 the default value is added programmatically. -->
-            <CheckBoxPreference
-                android:key="pref_show_setup_wizard_icon"
-                android:title="@string/show_setup_wizard_icon"
-                android:summary="@string/show_setup_wizard_icon_summary" />
+            android:defaultValue="true"
+            android:persistent="true" />
         </PreferenceScreen>
+    <PreferenceScreen
+        android:title="@string/settings_screen_advanced"
+        android:key="screen_advanced">
+        <!-- TODO: consolidate key preview dismiss delay with the key preview animation parameters. -->
+        <ListPreference
+            android:key="pref_key_preview_popup_dismiss_delay"
+            android:title="@string/key_preview_popup_dismiss_delay" />
+        <com.android.inputmethod.latin.settings.SeekBarDialogPreference
+            android:key="pref_vibration_duration_settings"
+            android:title="@string/prefs_keypress_vibration_duration_settings"
+            latin:maxValue="@integer/config_max_vibration_duration" />
+        <com.android.inputmethod.latin.settings.SeekBarDialogPreference
+            android:key="pref_keypress_sound_volume"
+            android:title="@string/prefs_keypress_sound_volume_settings"
+            latin:maxValue="100" /> <!-- percent -->
+        <!-- The settigs for showing setup wizard application icon shouldn't be persistent and
+             the default value is added programmatically. -->
+        <CheckBoxPreference
+            android:key="pref_show_setup_wizard_icon"
+            android:title="@string/show_setup_wizard_icon"
+            android:summary="@string/show_setup_wizard_icon_summary" />
+        <!-- title will be set programmatically to embed application name -->
+        <CheckBoxPreference
+            android:key="pref_enable_metrics_logging"
+            android:summary="@string/enable_metrics_logging_summary"
+            android:defaultValue="true"
+            android:persistent="true" />
         <PreferenceScreen
-            android:key="send_feedback"
-            android:title="@string/send_feedback" />
-        <PreferenceScreen
-            android:key="about_keyboard" />
-        <PreferenceScreen
-            android:key="debug_settings"
+            android:key="screen_debug"
             android:title="Debug settings"
-            android:persistent="true"
-            android:defaultValue="false" />
-    </PreferenceCategory>
+            android:defaultValue="false"
+            android:persistent="true" />
+        </PreferenceScreen>
 </PreferenceScreen>
diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml
index 0bcc5cb..ae29a8a 100644
--- a/java/res/xml/prefs_for_debug.xml
+++ b/java/res/xml/prefs_for_debug.xml
@@ -23,19 +23,19 @@
     <CheckBoxPreference
         android:key="debug_mode"
         android:title="@string/prefs_debug_mode"
-        android:persistent="true"
-        android:defaultValue="false" />
+        android:defaultValue="false"
+        android:persistent="true" />
     <CheckBoxPreference
         android:key="force_non_distinct_multitouch"
         android:title="@string/prefs_force_non_distinct_multitouch"
-        android:persistent="true"
-        android:defaultValue="false" />
+        android:defaultValue="false"
+        android:persistent="true" />
     <CheckBoxPreference
         android:key="pref_sliding_key_input_preview"
         android:title="@string/sliding_key_input_preview"
         android:summary="@string/sliding_key_input_preview_summary"
-        android:persistent="true"
-        android:defaultValue="true" />
+        android:defaultValue="true"
+        android:persistent="true" />
     <com.android.inputmethod.latin.settings.SeekBarDialogPreference
         android:key="pref_key_longpress_timeout"
         android:title="@string/prefs_key_longpress_timeout_settings"
diff --git a/java/res/xml/spell_checker_settings.xml b/java/res/xml/spell_checker_settings.xml
index de67e7f..3d95018 100644
--- a/java/res/xml/spell_checker_settings.xml
+++ b/java/res/xml/spell_checker_settings.xml
@@ -15,11 +15,12 @@
 -->
 
 <PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android">
-  <CheckBoxPreference
-     android:key="pref_spellcheck_use_contacts"
-     android:title="@string/use_contacts_for_spellchecking_option_title"
-     android:summary="@string/use_contacts_for_spellchecking_option_summary"
-     android:persistent="true"
-     android:defaultValue="true" />
+    xmlns:android="http://schemas.android.com/apk/res/android"
+>
+    <CheckBoxPreference
+        android:key="pref_spellcheck_use_contacts"
+        android:title="@string/use_contacts_for_spellchecking_option_title"
+        android:summary="@string/use_contacts_for_spellchecking_option_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
 </PreferenceScreen>
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 8182593..702efb3 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -451,7 +451,7 @@
 
         locatePreviewPlacerView();
         getLocationInWindow(mOriginCoords);
-        mKeyPreviewChoreographer.placeKeyPreviewAndShow(key, keyboard.mIconsSet, mKeyDrawParams,
+        mKeyPreviewChoreographer.placeAndShowKeyPreview(key, keyboard.mIconsSet, mKeyDrawParams,
                 getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated());
     }
 
@@ -554,11 +554,11 @@
             // though there may be some chances that the value is zero. <code>width == 0</code>
             // will cause zero-division error at
             // {@link MoreKeysKeyboardParams#setParameters(int,int,int,int,int,int,boolean,int)}.
-            final boolean singleMoreKeyWithPreview = mKeyPreviewDrawParams.isPopupEnabled()
+            final boolean isSingleMoreKeyWithPreview = mKeyPreviewDrawParams.isPopupEnabled()
                     && !key.noKeyPreview() && moreKeys.length == 1
                     && mKeyPreviewDrawParams.getVisibleWidth() > 0;
             final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder(
-                    context, key, getKeyboard(), singleMoreKeyWithPreview,
+                    context, key, getKeyboard(), isSingleMoreKeyWithPreview,
                     mKeyPreviewDrawParams.getVisibleWidth(),
                     mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key));
             moreKeysKeyboard = builder.build();
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index 353e07c..e0184d7 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -261,13 +261,13 @@
          * @param context the context of {@link MoreKeysKeyboardView}.
          * @param key the {@link Key} that invokes more keys keyboard.
          * @param keyboard the {@link Keyboard} that contains the parentKey.
-         * @param singleMoreKeyWithPreview true if the <code>key</code> has only one more key
-         *        and key popup preview is enabled.
+         * @param isSingleMoreKeyWithPreview true if the <code>key</code> has just a single
+         *        "more key" and its key popup preview is enabled.
          * @param keyPreviewDrawParams the parameter to place key preview.
-         * @param paintToMeasure the {@link Paint} object to measure a more key width
+         * @param paintToMeasure the {@link Paint} object to measure a "more key" width
          */
         public Builder(final Context context, final Key key, final Keyboard keyboard,
-                final boolean singleMoreKeyWithPreview, final int keyPreviewVisibleWidth,
+                final boolean isSingleMoreKeyWithPreview, final int keyPreviewVisibleWidth,
                 final int keyPreviewVisibleHeight, final Paint paintToMeasure) {
             super(context, new MoreKeysKeyboardParams());
             load(keyboard.mMoreKeysTemplate, keyboard.mId);
@@ -275,10 +275,11 @@
             // TODO: More keys keyboard's vertical gap is currently calculated heuristically.
             // Should revise the algorithm.
             mParams.mVerticalGap = keyboard.mVerticalGap / 2;
+            // This {@link MoreKeysKeyboard} is invoked from the <code>key</code>.
             mParentKey = key;
 
             final int keyWidth, rowHeight;
-            if (singleMoreKeyWithPreview) {
+            if (isSingleMoreKeyWithPreview) {
                 // Use pre-computed width and height if this more keys keyboard has only one key to
                 // mitigate visual flicker between key preview and more keys keyboard.
                 // Caveats for the visual assets: To achieve this effect, both the key preview
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
index 6fc300b..cd29c8d 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
@@ -105,7 +105,7 @@
         mFreeKeyPreviewViews.add(keyPreviewView);
     }
 
-    public void placeKeyPreviewAndShow(final Key key, final KeyboardIconsSet iconsSet,
+    public void placeAndShowKeyPreview(final Key key, final KeyboardIconsSet iconsSet,
             final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin,
             final ViewGroup placerView, final boolean withAnimation) {
         final KeyPreviewView keyPreviewView = getKeyPreviewView(key, placerView);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 42105e2..335e52f 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -64,11 +64,12 @@
     public static final int NOT_A_VALID_TIMESTAMP = -1;
 
     // Format to get unigram flags from native side via getWordPropertyNative().
-    private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 4;
+    private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 5;
     private static final int FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX = 0;
     private static final int FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX = 1;
     private static final int FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX = 2;
     private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
+    private static final int FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX = 4;
 
     // Format to get probability and historical info from native side via getWordPropertyNative().
     public static final int FORMAT_WORD_PROPERTY_OUTPUT_PROBABILITY_INFO_COUNT = 4;
@@ -176,10 +177,12 @@
     private static native int getBigramProbabilityNative(long dict, int[] word0,
             boolean isBeginningOfSentence, int[] word1);
     private static native void getWordPropertyNative(long dict, int[] word,
-            int[] outCodePoints, boolean[] outFlags, int[] outProbabilityInfo,
-            ArrayList<int[]> outBigramTargets, ArrayList<int[]> outBigramProbabilityInfo,
-            ArrayList<int[]> outShortcutTargets, ArrayList<Integer> outShortcutProbabilities);
-    private static native int getNextWordNative(long dict, int token, int[] outCodePoints);
+            boolean isBeginningOfSentence, int[] outCodePoints, boolean[] outFlags,
+            int[] outProbabilityInfo, ArrayList<int[]> outBigramTargets,
+            ArrayList<int[]> outBigramProbabilityInfo, ArrayList<int[]> outShortcutTargets,
+            ArrayList<Integer> outShortcutProbabilities);
+    private static native int getNextWordNative(long dict, int token, int[] outCodePoints,
+            boolean[] outIsBeginningOfSentence);
     private static native void getSuggestionsNative(long dict, long proximityInfo,
             long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times,
             int[] pointerIds, int[] inputCodePoints, int inputSize, int[] suggestOptions,
@@ -358,8 +361,8 @@
                 prevWordsInfo.mIsBeginningOfSentence, codePoints1);
     }
 
-    public WordProperty getWordProperty(final String word) {
-        if (TextUtils.isEmpty(word)) {
+    public WordProperty getWordProperty(final String word, final boolean isBeginningOfSentence) {
+        if (word == null) {
             return null;
         }
         final int[] codePoints = StringUtils.toCodePointArray(word);
@@ -371,14 +374,15 @@
         final ArrayList<int[]> outBigramProbabilityInfo = new ArrayList<>();
         final ArrayList<int[]> outShortcutTargets = new ArrayList<>();
         final ArrayList<Integer> outShortcutProbabilities = new ArrayList<>();
-        getWordPropertyNative(mNativeDict, codePoints, outCodePoints, outFlags, outProbabilityInfo,
-                outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
-                outShortcutProbabilities);
+        getWordPropertyNative(mNativeDict, codePoints, isBeginningOfSentence, outCodePoints,
+                outFlags, outProbabilityInfo, outBigramTargets, outBigramProbabilityInfo,
+                outShortcutTargets, outShortcutProbabilities);
         return new WordProperty(codePoints,
                 outFlags[FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX],
-                outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX], outProbabilityInfo,
+                outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX],
+                outFlags[FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX], outProbabilityInfo,
                 outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
                 outShortcutProbabilities);
     }
@@ -399,9 +403,12 @@
      */
     public GetNextWordPropertyResult getNextWordProperty(final int token) {
         final int[] codePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
-        final int nextToken = getNextWordNative(mNativeDict, token, codePoints);
+        final boolean[] isBeginningOfSentence = new boolean[1];
+        final int nextToken = getNextWordNative(mNativeDict, token, codePoints,
+                isBeginningOfSentence);
         final String word = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
-        return new GetNextWordPropertyResult(getWordProperty(word), nextToken);
+        return new GetNextWordPropertyResult(
+                getWordProperty(word, isBeginningOfSentence[0]), nextToken);
     }
 
     // Add a unigram entry to binary dictionary with unigram attributes in native code.
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 6199c7d..37879cf 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -122,12 +122,6 @@
         return mBinaryDictionary.isValidDictionary();
     }
 
-    // TODO: Remove and always enable beginning of sentence prediction. Currently, this is enabled
-    // only for ContextualDictionary.
-    protected boolean enableBeginningOfSentencePrediction() {
-        return false;
-    }
-
     /**
      * Creates a new expandable binary dictionary.
      *
@@ -426,10 +420,6 @@
                 if (mBinaryDictionary == null) {
                     return null;
                 }
-                if (composer.size() == 0 && prevWordsInfo.mIsBeginningOfSentence
-                        && !enableBeginningOfSentencePrediction()) {
-                    return null;
-                }
                 final ArrayList<SuggestedWordInfo> suggestions =
                         mBinaryDictionary.getSuggestions(composer, prevWordsInfo, proximityInfo,
                                 blockOffensiveWords, additionalFeaturesOptions, sessionId,
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 7364fc9..9d03e8a 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -110,6 +110,21 @@
         final boolean isOnlyFirstCharCapitalized =
                 wordComposer.isOrWillBeOnlyFirstCharCapitalized();
 
+        final ArrayList<SuggestedWordInfo> suggestionsContainer =
+                new ArrayList<>(suggestionResults);
+        final int suggestionsCount = suggestionsContainer.size();
+        if (isOnlyFirstCharCapitalized || shouldMakeSuggestionsAllUpperCase
+                || 0 != trailingSingleQuotesCount) {
+            for (int i = 0; i < suggestionsCount; ++i) {
+                final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+                final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
+                        wordInfo, suggestionResults.mLocale, shouldMakeSuggestionsAllUpperCase,
+                        isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
+                suggestionsContainer.set(i, transformedWordInfo);
+            }
+        }
+        SuggestedWordInfo.removeDups(typedWord, suggestionsContainer);
+
         // If resumed, then we don't want to upcase everything: resuming on a fully-capitalized
         // words is rarely done to switch to another fully-capitalized word, but usually to a
         // normal, non-capitalized suggestion.
@@ -167,20 +182,6 @@
                     suggestionResults.first(), consideredWord, mAutoCorrectionThreshold);
         }
 
-        final ArrayList<SuggestedWordInfo> suggestionsContainer =
-                new ArrayList<>(suggestionResults);
-        final int suggestionsCount = suggestionsContainer.size();
-        if (isOnlyFirstCharCapitalized || shouldMakeSuggestionsAllUpperCase
-                || 0 != trailingSingleQuotesCount) {
-            for (int i = 0; i < suggestionsCount; ++i) {
-                final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
-                final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
-                        wordInfo, suggestionResults.mLocale, shouldMakeSuggestionsAllUpperCase,
-                        isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
-                suggestionsContainer.set(i, transformedWordInfo);
-            }
-        }
-
         if (!TextUtils.isEmpty(typedWord)) {
             suggestionsContainer.add(0, new SuggestedWordInfo(typedWord,
                     SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED,
@@ -188,7 +189,6 @@
                     SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                     SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
         }
-        SuggestedWordInfo.removeDups(suggestionsContainer);
 
         final ArrayList<SuggestedWordInfo> suggestionsList;
         if (DBG && !suggestionsContainer.isEmpty()) {
@@ -237,7 +237,7 @@
             final SuggestedWordInfo rejected = suggestionsContainer.remove(0);
             suggestionsContainer.add(1, rejected);
         }
-        SuggestedWordInfo.removeDups(suggestionsContainer);
+        SuggestedWordInfo.removeDups(null /* typedWord */, suggestionsContainer);
 
         // For some reason some suggestions with MIN_VALUE are making their way here.
         // TODO: Find a more robust way to detect distractors.
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 72461e1..f22af79 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -316,10 +316,6 @@
             return mDebugString;
         }
 
-        public int codePointCount() {
-            return mCodePointCount;
-        }
-
         public int codePointAt(int i) {
             return mWord.codePointAt(i);
         }
@@ -333,23 +329,29 @@
             }
         }
 
-        // TODO: Consolidate this method and StringUtils.removeDupes() in the future.
-        public static void removeDups(ArrayList<SuggestedWordInfo> candidates) {
-            if (candidates.size() <= 1) {
+        // This will always remove the higher index if a duplicate is found.
+        public static void removeDups(final String typedWord,
+                ArrayList<SuggestedWordInfo> candidates) {
+            if (candidates.isEmpty()) {
                 return;
             }
-            int i = 1;
-            while (i < candidates.size()) {
-                final SuggestedWordInfo cur = candidates.get(i);
-                for (int j = 0; j < i; ++j) {
-                    final SuggestedWordInfo previous = candidates.get(j);
-                    if (cur.mWord.equals(previous.mWord)) {
-                        candidates.remove(cur.mScore < previous.mScore ? i : j);
-                        --i;
-                        break;
-                    }
+            if (!TextUtils.isEmpty(typedWord)) {
+                removeSuggestedWordInfoFrom(typedWord, candidates, -1 /* startIndexExclusive */);
+            }
+            for (int i = 0; i < candidates.size(); ++i) {
+                removeSuggestedWordInfoFrom(candidates.get(i).mWord, candidates,
+                        i /* startIndexExclusive */);
+            }
+        }
+
+        private static void removeSuggestedWordInfoFrom(final String word,
+                final ArrayList<SuggestedWordInfo> candidates, final int startIndexExclusive) {
+            for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) {
+                final SuggestedWordInfo previous = candidates.get(i);
+                if (word.equals(previous.mWord)) {
+                    candidates.remove(i);
+                    --i;
                 }
-                ++i;
             }
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 9462c38..4d3f5b5 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -728,14 +728,13 @@
             mConnection.setComposingText(getTextWithUnderline(
                     mWordComposer.getTypedWord()), 1);
         } else {
-            final boolean swapWeakSpace = maybeStripSpace(inputTransaction,
-                    inputTransaction.mEvent.isSuggestionStripPress());
+            final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
+                    inputTransaction, inputTransaction.mEvent.isSuggestionStripPress());
 
-            sendKeyCodePoint(settingsValues, codePoint);
-
-            if (swapWeakSpace) {
-                swapSwapperAndSpace(inputTransaction);
+            if (swapWeakSpace && trySwapSwapperAndSpace(inputTransaction)) {
                 mSpaceState = SpaceState.WEAK;
+            } else {
+                sendKeyCodePoint(settingsValues, codePoint);
             }
             // In case the "add to dictionary" hint was still displayed.
             mSuggestionStripViewAccessor.dismissAddToDictionaryHint();
@@ -780,7 +779,8 @@
             }
         }
 
-        final boolean swapWeakSpace = maybeStripSpace(inputTransaction, isFromSuggestionStrip);
+        final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
+                inputTransaction, isFromSuggestionStrip);
 
         final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint
                 && mConnection.isInsideDoubleQuoteOrAfterDigit();
@@ -804,16 +804,14 @@
             promotePhantomSpace(settingsValues);
         }
 
-        if (!shouldAvoidSendingCode) {
-            sendKeyCodePoint(settingsValues, codePoint);
-        }
-
-        if (Constants.CODE_SPACE == codePoint) {
-            if (maybeDoubleSpacePeriod(inputTransaction)) {
-                inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
-                inputTransaction.setRequiresUpdateSuggestions();
-                mSpaceState = SpaceState.DOUBLE;
-            } else if (!mSuggestedWords.isPunctuationSuggestions()) {
+        if (tryPerformDoubleSpacePeriod(inputTransaction)) {
+            mSpaceState = SpaceState.DOUBLE;
+            inputTransaction.setRequiresUpdateSuggestions();
+        } else if (swapWeakSpace && trySwapSwapperAndSpace(inputTransaction)) {
+            mSpaceState = SpaceState.SWAP_PUNCTUATION;
+            mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
+        } else if (Constants.CODE_SPACE == codePoint) {
+            if (!mSuggestedWords.isPunctuationSuggestions()) {
                 mSpaceState = SpaceState.WEAK;
             }
 
@@ -821,11 +819,12 @@
             if (wasComposingWord || mSuggestedWords.isEmpty()) {
                 inputTransaction.setRequiresUpdateSuggestions();
             }
+
+            if (!shouldAvoidSendingCode) {
+                sendKeyCodePoint(settingsValues, codePoint);
+            }
         } else {
-            if (swapWeakSpace) {
-                swapSwapperAndSpace(inputTransaction);
-                mSpaceState = SpaceState.SWAP_PUNCTUATION;
-            } else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
+            if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
                     && settingsValues.isUsuallyFollowedBySpace(codePoint))
                     || (Constants.CODE_DOUBLE_QUOTE == codePoint
                             && isInsideDoubleQuoteOrAfterDigit)) {
@@ -843,6 +842,8 @@
                 mSpaceState = SpaceState.PHANTOM;
             }
 
+            sendKeyCodePoint(settingsValues, codePoint);
+
             // Set punctuation right away. onUpdateSelection will fire but tests whether it is
             // already displayed or not, so it's okay.
             mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
@@ -1008,16 +1009,18 @@
      * This method will check that there are two characters before the cursor and that the first
      * one is a space before it does the actual swapping.
      * @param inputTransaction The transaction in progress.
+     * @return true if the swap has been performed, false if it was prevented by preliminary checks.
      */
-    private void swapSwapperAndSpace(final InputTransaction inputTransaction) {
-        final CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0);
-        // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
-        if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Constants.CODE_SPACE) {
-            mConnection.deleteSurroundingText(2, 0);
-            final String text = lastTwo.charAt(1) + " ";
-            mConnection.commitText(text, 1);
-            inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+    private boolean trySwapSwapperAndSpace(final InputTransaction inputTransaction) {
+        final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
+        if (Constants.CODE_SPACE != codePointBeforeCursor) {
+            return false;
         }
+        mConnection.deleteSurroundingText(1, 0);
+        final String text = inputTransaction.mEvent.getTextToCommit() + " ";
+        mConnection.commitText(text, 1);
+        inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+        return true;
     }
 
     /*
@@ -1026,8 +1029,8 @@
      * @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip.
      * @return whether we should swap the space instead of removing it.
      */
-    private boolean maybeStripSpace(final InputTransaction inputTransaction,
-            final boolean isFromSuggestionStrip) {
+    private boolean tryStripSpaceAndReturnWhetherShouldSwapInstead(
+            final InputTransaction inputTransaction, final boolean isFromSuggestionStrip) {
         final int codePoint = inputTransaction.mEvent.mCodePoint;
         if (Constants.CODE_ENTER == codePoint &&
                 SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) {
@@ -1068,37 +1071,42 @@
      * period-space sequence of characters. This typically happens when the user presses space
      * twice in a row quickly.
      * This method will check that the double-space-to-period is active in settings, that the
-     * two spaces have been input close enough together, and that the previous character allows
-     * for the transformation to take place. If all of these conditions are fulfilled, this
-     * method applies the transformation and returns true. Otherwise, it does nothing and
-     * returns false.
+     * two spaces have been input close enough together, that the typed character is a space
+     * and that the previous character allows for the transformation to take place. If all of
+     * these conditions are fulfilled, this method applies the transformation and returns true.
+     * Otherwise, it does nothing and returns false.
      *
      * @param inputTransaction The transaction in progress.
      * @return true if we applied the double-space-to-period transformation, false otherwise.
      */
-    private boolean maybeDoubleSpacePeriod(final InputTransaction inputTransaction) {
-        if (!inputTransaction.mSettingsValues.mUseDoubleSpacePeriod) return false;
-        if (!isDoubleSpacePeriodCountdownActive(inputTransaction)) return false;
-        // We only do this when we see two spaces and an accepted code point before the cursor.
-        // The code point may be a surrogate pair but the two spaces may not, so we need 4 chars.
-        final CharSequence lastThree = mConnection.getTextBeforeCursor(4, 0);
-        if (null == lastThree) return false;
-        final int length = lastThree.length();
-        if (length < 3) return false;
-        if (lastThree.charAt(length - 1) != Constants.CODE_SPACE) return false;
-        if (lastThree.charAt(length - 2) != Constants.CODE_SPACE) return false;
-        // We know there are spaces in pos -1 and -2, and we have at least three chars.
-        // If we have only three chars, isSurrogatePairs can't return true as charAt(1) is a space,
-        // so this is fine.
+    private boolean tryPerformDoubleSpacePeriod(final InputTransaction inputTransaction) {
+        // Check the setting, the typed character and the countdown. If any of the conditions is
+        // not fulfilled, return false.
+        if (!inputTransaction.mSettingsValues.mUseDoubleSpacePeriod
+                || Constants.CODE_SPACE != inputTransaction.mEvent.mCodePoint
+                || !isDoubleSpacePeriodCountdownActive(inputTransaction)) {
+            return false;
+        }
+        // We only do this when we see one space and an accepted code point before the cursor.
+        // The code point may be a surrogate pair but the space may not, so we need 3 chars.
+        final CharSequence lastTwo = mConnection.getTextBeforeCursor(3, 0);
+        if (null == lastTwo) return false;
+        final int length = lastTwo.length();
+        if (length < 2) return false;
+        if (lastTwo.charAt(length - 1) != Constants.CODE_SPACE) return false;
+        // We know there is a space in pos -1, and we have at least two chars. If we have only two
+        // chars, isSurrogatePairs can't return true as charAt(1) is a space, so this is fine.
         final int firstCodePoint =
-                Character.isSurrogatePair(lastThree.charAt(0), lastThree.charAt(1)) ?
-                        Character.codePointAt(lastThree, 0) : lastThree.charAt(length - 3);
+                Character.isSurrogatePair(lastTwo.charAt(0), lastTwo.charAt(1)) ?
+                        Character.codePointAt(lastTwo, length - 3) : lastTwo.charAt(length - 2);
         if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) {
             cancelDoubleSpacePeriodCountdown();
-            mConnection.deleteSurroundingText(2, 0);
+            mConnection.deleteSurroundingText(1, 0);
             final String textToInsert = inputTransaction.mSettingsValues.mSpacingAndPunctuations
                     .mSentenceSeparatorAndSpace;
             mConnection.commitText(textToInsert, 1);
+            inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+            inputTransaction.setRequiresUpdateSuggestions();
             return true;
         }
         return false;
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index 31cb597..cd78e22 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -70,8 +70,8 @@
     // Construct word property using information from native code.
     // This represents invalid word when the probability is BinaryDictionary.NOT_A_PROBABILITY.
     public WordProperty(final int[] codePoints, final boolean isNotAWord,
-            final boolean isBlacklisted, final boolean hasBigram,
-            final boolean hasShortcuts, final int[] probabilityInfo,
+            final boolean isBlacklisted, final boolean hasBigram, final boolean hasShortcuts,
+            final boolean isBeginningOfSentence, final int[] probabilityInfo,
             final ArrayList<int[]> bigramTargets, final ArrayList<int[]> bigramProbabilityInfo,
             final ArrayList<int[]> shortcutTargets,
             final ArrayList<Integer> shortcutProbabilities) {
@@ -79,7 +79,7 @@
         mProbabilityInfo = createProbabilityInfoFromArray(probabilityInfo);
         mShortcutTargets = new ArrayList<>();
         mBigrams = new ArrayList<>();
-        mIsBeginningOfSentence = false;
+        mIsBeginningOfSentence = isBeginningOfSentence;
         mIsNotAWord = isNotAWord;
         mIsBlacklistEntry = isBlacklisted;
         mHasShortcuts = hasShortcuts;
diff --git a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
index a96018f..ac55b93 100644
--- a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
@@ -43,11 +43,6 @@
     }
 
     @Override
-    protected boolean enableBeginningOfSentencePrediction() {
-        return true;
-    }
-
-    @Override
     public boolean isValidWord(final String word) {
         // Strings out of this dictionary should not be considered existing words.
         return false;
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index 845ddb3..c17e868 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -21,14 +21,13 @@
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.Process;
-import android.preference.CheckBoxPreference;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
+import android.preference.TwoStatePreference;
 
-import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.DictionaryDumpBroadcastReceiver;
 import com.android.inputmethod.latin.DictionaryFacilitator;
 import com.android.inputmethod.latin.R;
@@ -57,7 +56,7 @@
     public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
 
     private boolean mServiceNeedsRestart = false;
-    private CheckBoxPreference mDebugMode;
+    private TwoStatePreference mDebugMode;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -107,7 +106,7 @@
                         res, R.fraction.config_key_preview_dismiss_end_scale));
 
         mServiceNeedsRestart = false;
-        mDebugMode = (CheckBoxPreference) findPreference(PREF_DEBUG_MODE);
+        mDebugMode = (TwoStatePreference) findPreference(PREF_DEBUG_MODE);
         updateDebugMode();
     }
 
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 2358477..fb1a210 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -39,8 +39,14 @@
 
 public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = Settings.class.getSimpleName();
+    // Settings screens
+    public static final String SCREEN_INPUT = "screen_input";
+    public static final String SCREEN_MULTI_LINGUAL = "screen_multi_lingual";
+    public static final String SCREEN_GESTURE = "screen_gesture";
+    public static final String SCREEN_CORRECTION = "screen_correction";
+    public static final String SCREEN_ADVANCED = "screen_advanced";
+    public static final String SCREEN_DEBUG = "screen_debug";
     // In the same order as xml/prefs.xml
-    public static final String PREF_GENERAL_SETTINGS = "general_settings";
     public static final String PREF_AUTO_CAP = "auto_cap";
     public static final String PREF_VIBRATE_ON = "vibrate_on";
     public static final String PREF_SOUND_ON = "sound_on";
@@ -48,13 +54,10 @@
     // PREF_VOICE_MODE_OBSOLETE is obsolete. Use PREF_VOICE_INPUT_KEY instead.
     public static final String PREF_VOICE_MODE_OBSOLETE = "voice_mode";
     public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key";
-    public static final String PREF_CORRECTION_SETTINGS = "correction_settings";
     public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary";
     public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
     public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
     public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
-    public static final String PREF_MISC_SETTINGS = "misc_settings";
-    public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
     public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
     public static final String PREF_KEY_USE_PERSONALIZED_DICTS = "pref_key_use_personalized_dicts";
     public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD =
@@ -75,7 +78,6 @@
     public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
             "pref_key_preview_popup_dismiss_delay";
     public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
-    public static final String PREF_GESTURE_SETTINGS = "gesture_typing_settings";
     public static final String PREF_GESTURE_INPUT = "gesture_input";
     public static final String PREF_VIBRATION_DURATION_SETTINGS =
             "pref_vibration_duration_settings";
@@ -89,7 +91,6 @@
 
     public static final String PREF_INPUT_LANGUAGE = "input_language";
     public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
-    public static final String PREF_DEBUG_SETTINGS = "debug_settings";
     public static final String PREF_KEY_IS_INTERNAL = "pref_key_is_internal";
 
     public static final String PREF_ENABLE_METRICS_LOGGING = "pref_enable_metrics_logging";
@@ -105,8 +106,6 @@
             "pref_last_used_personalization_dict_wiped_time";
     private static final String PREF_CORPUS_HANDLES_FOR_PERSONALIZATION =
             "pref_corpus_handles_for_personalization";
-    public static final String PREF_SEND_FEEDBACK = "send_feedback";
-    public static final String PREF_ABOUT_KEYBOARD = "about_keyboard";
 
     // Emoji
     public static final String PREF_EMOJI_RECENT_KEYS = "emoji_recent_keys";
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
index 5eb0377..689f878 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
@@ -27,13 +27,15 @@
 import android.media.AudioManager;
 import android.os.Build;
 import android.os.Bundle;
-import android.preference.CheckBoxPreference;
 import android.preference.ListPreference;
 import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
+import android.preference.TwoStatePreference;
 import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
@@ -61,6 +63,10 @@
             DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS
             || Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2;
 
+    private static final int NO_MENU_GROUP = Menu.NONE; // We don't care about menu grouping.
+    private static final int MENU_FEEDBACK = Menu.FIRST; // The first menu item id and order.
+    private static final int MENU_ABOUT = Menu.FIRST + 1; // The second menu item id and order.
+
     private void setPreferenceEnabled(final String preferenceKey, final boolean enabled) {
         final Preference preference = findPreference(preferenceKey);
         if (preference != null) {
@@ -93,6 +99,7 @@
     @Override
     public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
+        setHasOptionsMenu(true);
         setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
         setSubtypeEnablerTitle(R.string.select_language);
         addPreferencesFromResource(R.xml.prefs);
@@ -117,66 +124,48 @@
 
         ensureConsistencyOfAutoCorrectionSettings();
 
-        final PreferenceGroup generalSettings =
-                (PreferenceGroup) findPreference(Settings.PREF_GENERAL_SETTINGS);
-        final PreferenceGroup miscSettings =
-                (PreferenceGroup) findPreference(Settings.PREF_MISC_SETTINGS);
+        final PreferenceScreen inputScreen =
+                (PreferenceScreen) findPreference(Settings.SCREEN_INPUT);
+        final PreferenceScreen multiLingualScreen =
+                (PreferenceScreen) findPreference(Settings.SCREEN_MULTI_LINGUAL);
+        final PreferenceScreen gestureScreen =
+                (PreferenceScreen) findPreference(Settings.SCREEN_GESTURE);
+        final PreferenceScreen correctionScreen =
+                (PreferenceScreen) findPreference(Settings.SCREEN_CORRECTION);
+        final PreferenceScreen advancedScreen =
+                (PreferenceScreen) findPreference(Settings.SCREEN_ADVANCED);
+        final PreferenceScreen debugScreen =
+                (PreferenceScreen) findPreference(Settings.SCREEN_DEBUG);
 
-        final Preference debugSettings = findPreference(Settings.PREF_DEBUG_SETTINGS);
-        if (debugSettings != null) {
-            if (Settings.isInternal(prefs)) {
-                final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
-                debugSettingsIntent.setClassName(
-                        context.getPackageName(), DebugSettingsActivity.class.getName());
-                debugSettings.setIntent(debugSettingsIntent);
-            } else {
-                miscSettings.removePreference(debugSettings);
-            }
-        }
-
-        final Preference feedbackSettings = findPreference(Settings.PREF_SEND_FEEDBACK);
-        final Preference aboutSettings = findPreference(Settings.PREF_ABOUT_KEYBOARD);
-        if (feedbackSettings != null) {
-            if (FeedbackUtils.isFeedbackFormSupported()) {
-                feedbackSettings.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-                    @Override
-                    public boolean onPreferenceClick(final Preference pref) {
-                        FeedbackUtils.showFeedbackForm(getActivity());
-                        return true;
-                    }
-                });
-                aboutSettings.setTitle(FeedbackUtils.getAboutKeyboardTitleResId());
-                aboutSettings.setIntent(FeedbackUtils.getAboutKeyboardIntent(getActivity()));
-            } else {
-                miscSettings.removePreference(feedbackSettings);
-                miscSettings.removePreference(aboutSettings);
-            }
+        if (Settings.isInternal(prefs)) {
+            final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
+            debugSettingsIntent.setClassName(
+                    context.getPackageName(), DebugSettingsActivity.class.getName());
+            debugScreen.setIntent(debugSettingsIntent);
+        } else {
+            advancedScreen.removePreference(debugScreen);
         }
 
         final boolean showVoiceKeyOption = res.getBoolean(
                 R.bool.config_enable_show_voice_key_option);
         if (!showVoiceKeyOption) {
-            removePreference(Settings.PREF_VOICE_INPUT_KEY, generalSettings);
+            removePreference(Settings.PREF_VOICE_INPUT_KEY, inputScreen);
         }
 
-        final PreferenceGroup advancedSettings =
-                (PreferenceGroup) findPreference(Settings.PREF_ADVANCED_SETTINGS);
         if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) {
-            removePreference(Settings.PREF_VIBRATE_ON, generalSettings);
-            removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedSettings);
+            removePreference(Settings.PREF_VIBRATE_ON, inputScreen);
+            removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedScreen);
         }
         if (!Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS) {
+            removePreference(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, multiLingualScreen);
             removePreference(
-                    Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, advancedSettings);
-            removePreference(
-                    Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, advancedSettings);
+                    Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, multiLingualScreen);
         }
 
-
         // TODO: consolidate key preview dismiss delay with the key preview animation parameters.
         if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) {
-            removePreference(Settings.PREF_POPUP_ON, generalSettings);
-            removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedSettings);
+            removePreference(Settings.PREF_POPUP_ON, inputScreen);
+            removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedScreen);
         } else {
             // TODO: Cleanup this setup.
             final ListPreference keyPreviewPopupDismissDelay =
@@ -199,18 +188,16 @@
         }
 
         if (!res.getBoolean(R.bool.config_setup_wizard_available)) {
-            removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON, advancedSettings);
+            removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON, advancedScreen);
         }
 
-        final PreferenceGroup textCorrectionGroup =
-                (PreferenceGroup) findPreference(Settings.PREF_CORRECTION_SETTINGS);
         final PreferenceScreen dictionaryLink =
                 (PreferenceScreen) findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
         final Intent intent = dictionaryLink.getIntent();
         intent.setClassName(context.getPackageName(), DictionarySettingsActivity.class.getName());
         final int number = context.getPackageManager().queryIntentActivities(intent, 0).size();
         if (0 >= number) {
-            textCorrectionGroup.removePreference(dictionaryLink);
+            correctionScreen.removePreference(dictionaryLink);
         }
 
         if (ProductionFlag.IS_METRICS_LOGGING_SUPPORTED) {
@@ -224,7 +211,7 @@
                 enableMetricsLogging.setTitle(enableMetricsLoggingTitle);
             }
         } else {
-            removePreference(Settings.PREF_ENABLE_METRICS_LOGGING, textCorrectionGroup);
+            removePreference(Settings.PREF_ENABLE_METRICS_LOGGING, advancedScreen);
         }
 
         final Preference editPersonalDictionary =
@@ -238,7 +225,7 @@
         }
 
         if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) {
-            removePreference(Settings.PREF_GESTURE_SETTINGS, getPreferenceScreen());
+            getPreferenceScreen().removePreference(gestureScreen);
         }
 
         AdditionalFeaturesSettingUtils.addAdditionalFeaturesPreferences(context, this);
@@ -261,8 +248,8 @@
             voiceInputKeyOption.setSummary(isShortcutImeEnabled ? null
                     : res.getText(R.string.voice_input_disabled_summary));
         }
-        final CheckBoxPreference showSetupWizardIcon =
-                (CheckBoxPreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
+        final TwoStatePreference showSetupWizardIcon =
+                (TwoStatePreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
         if (showSetupWizardIcon != null) {
             showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, getActivity()));
         }
@@ -476,4 +463,33 @@
             userDictionaryPreference.setFragment(UserDictionaryList.class.getName());
         }
     }
+
+    @Override
+    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+        if (FeedbackUtils.isFeedbackFormSupported()) {
+            menu.add(NO_MENU_GROUP, MENU_FEEDBACK /* itemId */, MENU_FEEDBACK /* order */,
+                    R.string.send_feedback);
+        }
+        final int aboutResId = FeedbackUtils.getAboutKeyboardTitleResId();
+        if (aboutResId != 0) {
+            menu.add(NO_MENU_GROUP, MENU_ABOUT /* itemId */, MENU_ABOUT /* order */, aboutResId);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        final int itemId = item.getItemId();
+        if (itemId == MENU_FEEDBACK) {
+            FeedbackUtils.showFeedbackForm(getActivity());
+            return true;
+        }
+        if (itemId == MENU_ABOUT) {
+            final Intent aboutIntent = FeedbackUtils.getAboutKeyboardIntent(getActivity());
+            if (aboutIntent != null) {
+                startActivity(aboutIntent);
+                return true;
+            }
+        }
+        return super.onOptionsItemSelected(item);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
index c660075..34f59e8 100644
--- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
@@ -31,6 +31,7 @@
     public static final String HISTORICAL_INFO_TAG = "historicalInfo";
     public static final String HISTORICAL_INFO_SEPARATOR = ":";
     public static final String WORD_TAG = "word";
+    public static final String BEGINNING_OF_SENTENCE_TAG = "beginning_of_sentence";
     public static final String NOT_A_WORD_TAG = "not_a_word";
     public static final String BLACKLISTED_TAG = "blacklisted";
 
@@ -56,6 +57,9 @@
         builder.append(" " + WORD_TAG + "=" + wordProperty.mWord);
         builder.append(",");
         builder.append(formatProbabilityInfo(wordProperty.mProbabilityInfo));
+        if (wordProperty.mIsBeginningOfSentence) {
+            builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true");
+        }
         if (wordProperty.mIsNotAWord) {
             builder.append("," + NOT_A_WORD_TAG + "=true");
         }
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index c2cd2ad..2654a4a 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -301,7 +301,7 @@
 // If token is 0, this method newly starts iterating the dictionary. This method returns 0 when
 // the dictionary does not have a next word.
 static jint latinime_BinaryDictionary_getNextWord(JNIEnv *env, jclass clazz,
-        jlong dict, jint token, jintArray outCodePoints) {
+        jlong dict, jint token, jintArray outCodePoints, jbooleanArray outIsBeginningOfSentence) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return 0;
     const jsize codePointBufSize = env->GetArrayLength(outCodePoints);
@@ -317,19 +317,39 @@
     JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
             MAX_WORD_LENGTH /* maxLength */, wordCodePoints, wordCodePointCount,
             false /* needsNullTermination */);
+    bool isBeginningOfSentence = false;
+    if (wordCodePointCount > 0 && wordCodePoints[0] == CODE_POINT_BEGINNING_OF_SENTENCE) {
+        isBeginningOfSentence = true;
+    }
+    JniDataUtils::putBooleanToArray(env, outIsBeginningOfSentence, 0 /* index */,
+            isBeginningOfSentence);
     return nextToken;
 }
 
 static void latinime_BinaryDictionary_getWordProperty(JNIEnv *env, jclass clazz,
-        jlong dict, jintArray word, jintArray outCodePoints, jbooleanArray outFlags,
-        jintArray outProbabilityInfo, jobject outBigramTargets, jobject outBigramProbabilityInfo,
-        jobject outShortcutTargets, jobject outShortcutProbabilities) {
+        jlong dict, jintArray word, jboolean isBeginningOfSentence, jintArray outCodePoints,
+        jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outBigramTargets,
+        jobject outBigramProbabilityInfo, jobject outShortcutTargets,
+        jobject outShortcutProbabilities) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return;
     const jsize wordLength = env->GetArrayLength(word);
-    int wordCodePoints[wordLength];
+    if (wordLength > MAX_WORD_LENGTH) {
+        AKLOGE("Invalid wordLength: %d", wordLength);
+        return;
+    }
+    int wordCodePoints[MAX_WORD_LENGTH];
     env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
-    const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints, wordLength);
+    int codePointCount = wordLength;
+    if (isBeginningOfSentence) {
+        codePointCount = CharUtils::attachBeginningOfSentenceMarker(
+                wordCodePoints, wordLength, MAX_WORD_LENGTH);
+        if (codePointCount < 0) {
+            AKLOGE("Cannot attach Beginning-of-Sentence marker.");
+            return;
+        }
+    }
+    const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints, codePointCount);
     wordProperty.outputProperties(env, outCodePoints, outFlags, outProbabilityInfo,
             outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
             outShortcutProbabilities);
@@ -554,7 +574,6 @@
         return false;
     }
 
-    // TODO: Migrate historical information.
     int wordCodePoints[MAX_WORD_LENGTH];
     int wordCodePointCount = 0;
     int token = 0;
@@ -563,6 +582,10 @@
         token = dictionary->getNextWordAndNextToken(token, wordCodePoints, &wordCodePointCount);
         const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints,
                 wordCodePointCount);
+        if (wordCodePoints[0] == CODE_POINT_BEGINNING_OF_SENTENCE) {
+            // Skip beginning-of-sentence unigram.
+            continue;
+        }
         if (dictionaryStructureWithBufferPolicy->needsToRunGC(true /* mindsBlockByGC */)) {
             dictionaryStructureWithBufferPolicy = runGCAndGetNewStructurePolicy(
                     std::move(dictionaryStructureWithBufferPolicy), dictFilePathChars);
@@ -592,7 +615,7 @@
             }
         }
         const PrevWordsInfo prevWordsInfo(wordCodePoints, wordCodePointCount,
-                false /* isBeginningOfSentence */);
+                wordProperty.getUnigramProperty()->representsBeginningOfSentence());
         for (const BigramProperty &bigramProperty : *wordProperty.getBigramProperties()) {
             if (!dictionaryStructureWithBufferPolicy->addNgramEntry(&prevWordsInfo,
                     &bigramProperty)) {
@@ -669,13 +692,13 @@
     },
     {
         const_cast<char *>("getWordPropertyNative"),
-        const_cast<char *>("(J[I[I[Z[ILjava/util/ArrayList;Ljava/util/ArrayList;"
+        const_cast<char *>("(J[IZ[I[Z[ILjava/util/ArrayList;Ljava/util/ArrayList;"
                 "Ljava/util/ArrayList;Ljava/util/ArrayList;)V"),
         reinterpret_cast<void *>(latinime_BinaryDictionary_getWordProperty)
     },
     {
         const_cast<char *>("getNextWordNative"),
-        const_cast<char *>("(JI[I)I"),
+        const_cast<char *>("(JI[I[Z)I"),
         reinterpret_cast<void *>(latinime_BinaryDictionary_getNextWord)
     },
     {
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 6f5f808..5bdd560 100644
--- a/native/jni/src/suggest/core/dictionary/property/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
@@ -28,7 +28,8 @@
             MAX_WORD_LENGTH /* maxLength */, mCodePoints.data(), mCodePoints.size(),
             false /* needsNullTermination */);
     jboolean flags[] = {mUnigramProperty.isNotAWord(), mUnigramProperty.isBlacklisted(),
-            !mBigrams.empty(), mUnigramProperty.hasShortcuts()};
+            !mBigrams.empty(), mUnigramProperty.hasShortcuts(),
+            mUnigramProperty.representsBeginningOfSentence()};
     env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
     int probabilityInfo[] = {mUnigramProperty.getProbability(), mUnigramProperty.getTimestamp(),
             mUnigramProperty.getLevel(), mUnigramProperty.getCount()};
diff --git a/native/jni/src/utils/char_utils.h b/native/jni/src/utils/char_utils.h
index f28ed56..6378650 100644
--- a/native/jni/src/utils/char_utils.h
+++ b/native/jni/src/utils/char_utils.h
@@ -98,6 +98,10 @@
     // Beginning-of-Sentence.
     static AK_FORCE_INLINE int attachBeginningOfSentenceMarker(int *const codePoints,
             const int codePointCount, const int maxCodePoint) {
+        if (codePointCount > 0 && codePoints[0] == CODE_POINT_BEGINNING_OF_SENTENCE) {
+            // Marker has already been attached.
+            return codePointCount;
+        }
         if (codePointCount >= maxCodePoint) {
             // the code points cannot be marked as a Beginning-of-Sentence.
             return 0;
diff --git a/native/jni/src/utils/jni_data_utils.h b/native/jni/src/utils/jni_data_utils.h
index 67a66fd..3514aee 100644
--- a/native/jni/src/utils/jni_data_utils.h
+++ b/native/jni/src/utils/jni_data_utils.h
@@ -69,18 +69,23 @@
     static void outputCodePoints(JNIEnv *env, jintArray intArrayToOutputCodePoints, const int start,
             const int maxLength, const int *const codePoints, const int codePointCount,
             const bool needsNullTermination) {
-        const int outputCodePointCount = std::min(maxLength, codePointCount);
-        int outputCodePonts[outputCodePointCount];
-        for (int i = 0; i < outputCodePointCount; ++i) {
+        const int codePointBufSize = std::min(maxLength, codePointCount);
+        int outputCodePonts[codePointBufSize];
+        int outputCodePointCount = 0;
+        for (int i = 0; i < codePointBufSize; ++i) {
             const int codePoint = codePoints[i];
+            int codePointToOutput = codePoint;
             if (!CharUtils::isInUnicodeSpace(codePoint)) {
-                outputCodePonts[i] = CODE_POINT_REPLACEMENT_CHARACTER;
+                if (codePoint == CODE_POINT_BEGINNING_OF_SENTENCE) {
+                    // Just skip Beginning-of-Sentence marker.
+                    continue;
+                }
+                codePointToOutput = CODE_POINT_REPLACEMENT_CHARACTER;
             } else if (codePoint >= 0x01 && codePoint <= 0x1F) {
                 // Control code.
-                outputCodePonts[i] = CODE_POINT_REPLACEMENT_CHARACTER;
-            } else {
-                outputCodePonts[i] = codePoint;
+                codePointToOutput = CODE_POINT_REPLACEMENT_CHARACTER;
             }
+            outputCodePonts[outputCodePointCount++] = codePointToOutput;
         }
         env->SetIntArrayRegion(intArrayToOutputCodePoints, start, outputCodePointCount,
                 outputCodePonts);
@@ -90,6 +95,11 @@
         }
     }
 
+    static void putBooleanToArray(JNIEnv *env, jbooleanArray array, const int index,
+            const jboolean value) {
+        env->SetBooleanArrayRegion(array, index, 1 /* len */, &value);
+    }
+
     static void putIntToArray(JNIEnv *env, jintArray array, const int index, const int value) {
         env->SetIntArrayRegion(array, index, 1 /* len */, &value);
     }
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 160b08c..83ea193 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -994,7 +994,8 @@
                 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
                 Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
 
-        final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord");
+        final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
+                false /* isBeginningOfSentence */);
         assertFalse(invalidWordProperty.isValid());
 
         final ArrayList<String> words = new ArrayList<>();
@@ -1017,7 +1018,8 @@
             }
             words.add(word);
             wordProbabilities.put(word, unigramProbability);
-            final WordProperty wordProperty = binaryDictionary.getWordProperty(word);
+            final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
+                    false /* isBeginningOfSentence */);
             assertEquals(word, wordProperty.mWord);
             assertTrue(wordProperty.isValid());
             assertEquals(isNotAWord, wordProperty.mIsNotAWord);
@@ -1057,7 +1059,8 @@
                 continue;
             }
             final HashSet<String> bigramWord1s = bigrams.get(word0);
-            final WordProperty wordProperty = binaryDictionary.getWordProperty(word0);
+            final WordProperty wordProperty = binaryDictionary.getWordProperty(word0,
+                    false /* isBeginningOfSentence */);
             assertEquals(bigramWord1s.size(), wordProperty.mBigrams.size());
             for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
                 final String word1 = wordProperty.mBigrams.get(j).mWord;
@@ -1094,7 +1097,8 @@
                 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
                 Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
 
-        final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord");
+        final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
+                false /* isBeginningOfSentence */);
         assertFalse(invalidWordProperty.isValid());
 
         final ArrayList<String> words = new ArrayList<>();
@@ -1188,7 +1192,8 @@
         binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
                 shortcutProbability, false /* isBeginningOfSentence */,
                 false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
-        WordProperty wordProperty = binaryDictionary.getWordProperty("aaa");
+        WordProperty wordProperty = binaryDictionary.getWordProperty("aaa",
+                false /* isBeginningOfSentence */);
         assertEquals(1, wordProperty.mShortcutTargets.size());
         assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
         assertEquals(shortcutProbability, wordProperty.mShortcutTargets.get(0).getProbability());
@@ -1196,7 +1201,8 @@
         binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
                 updatedShortcutProbability, false /* isBeginningOfSentence */,
                 false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
-        wordProperty = binaryDictionary.getWordProperty("aaa");
+        wordProperty = binaryDictionary.getWordProperty("aaa",
+                false /* isBeginningOfSentence */);
         assertEquals(1, wordProperty.mShortcutTargets.size());
         assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
         assertEquals(updatedShortcutProbability,
@@ -1207,7 +1213,8 @@
         final HashMap<String, Integer> shortcutTargets = new HashMap<>();
         shortcutTargets.put("zzz", updatedShortcutProbability);
         shortcutTargets.put("yyy", shortcutProbability);
-        wordProperty = binaryDictionary.getWordProperty("aaa");
+        wordProperty = binaryDictionary.getWordProperty("aaa",
+                false /* isBeginningOfSentence */);
         assertEquals(2, wordProperty.mShortcutTargets.size());
         for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
             assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
@@ -1218,7 +1225,8 @@
         shortcutTargets.put("zzz", updatedShortcutProbability);
         shortcutTargets.put("yyy", shortcutProbability);
         binaryDictionary.flushWithGC();
-        wordProperty = binaryDictionary.getWordProperty("aaa");
+        wordProperty = binaryDictionary.getWordProperty("aaa",
+                false /* isBeginningOfSentence */);
         assertEquals(2, wordProperty.mShortcutTargets.size());
         for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
             assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
@@ -1288,7 +1296,8 @@
         }
 
         for (final String word : words) {
-            final WordProperty wordProperty = binaryDictionary.getWordProperty(word);
+            final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
+                    false /* isBeginningOfSentence */);
             assertEquals((int)unigramProbabilities.get(word),
                     wordProperty.mProbabilityInfo.mProbability);
             if (!shortcutTargets.containsKey(word)) {
@@ -1332,6 +1341,8 @@
         binaryDictionary.addUnigramEntry("ddd", unigramProbability, null /* shortcutTarget */,
                 Dictionary.NOT_A_PROBABILITY, false /* isBeginningOfSentence */,
                 true /* isNotAWord */, true /* isBlacklisted */, 0 /* timestamp */);
+        binaryDictionary.addNgramEntry(PrevWordsInfo.BEGINNING_OF_SENTENCE,
+                "aaa", bigramProbability, 0 /* timestamp */);
         assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
         assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
         assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
@@ -1343,12 +1354,16 @@
         assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
         if (canCheckBigramProbability(toFormatVersion)) {
             assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bbb"));
+            assertEquals(bigramProbability, binaryDictionary.getNgramProbability(
+                    PrevWordsInfo.BEGINNING_OF_SENTENCE, "aaa"));
         }
         assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
-        WordProperty wordProperty = binaryDictionary.getWordProperty("ccc");
+        WordProperty wordProperty = binaryDictionary.getWordProperty("ccc",
+                false /* isBeginningOfSentence */);
         assertEquals(1, wordProperty.mShortcutTargets.size());
         assertEquals("xxx", wordProperty.mShortcutTargets.get(0).mWord);
-        wordProperty = binaryDictionary.getWordProperty("ddd");
+        wordProperty = binaryDictionary.getWordProperty("ddd",
+                false /* isBeginningOfSentence */);
         assertTrue(wordProperty.mIsBlacklistEntry);
         assertTrue(wordProperty.mIsNotAWord);
     }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index 4b332ca..406046a 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -614,7 +614,8 @@
                 0 /* offset */, file.length(), true /* useFullEditDistance */,
                 Locale.ENGLISH, dictName, false /* isUpdatable */);
         for (final String word : words) {
-            final WordProperty wordProperty = binaryDictionary.getWordProperty(word);
+            final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
+                    false /* isBeginningOfSentence */);
             assertEquals(word, wordProperty.mWord);
             assertEquals(UNIGRAM_FREQ, wordProperty.getProbability());
             if (shortcuts.containsKey(word)) {