Merge "Refactor SpellCheckerProximityInfo as extending ProximityInfo"
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index 49855e3..17d11c0 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -44,7 +44,7 @@
         </service>
 
         <service android:name=".spellcheck.AndroidSpellCheckerService"
-                 android:label="@string/spell_checker_service_name"
+                 android:label="@string/aosp_spell_checker_service_name"
                  android:permission="android.permission.BIND_TEXT_SERVICE">
             <intent-filter>
                 <action android:name="android.service.textservice.SpellCheckerService" />
@@ -69,7 +69,7 @@
             </intent-filter>
         </receiver>
 
-        <activity android:name="SettingsActivity" android:label="@string/english_ime_settings"
+        <activity android:name="SettingsActivity" android:label="@string/aosp_android_keyboard_ime_settings"
                   android:uiOptions="splitActionBarWhenNarrow">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -77,7 +77,7 @@
         </activity>
 
         <activity android:name="com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsActivity"
-                  android:label="@string/android_spell_checker_settings">
+                  android:label="@string/aosp_android_spell_checker_service_settings">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
@@ -95,6 +95,12 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name=".DictionaryPackInstallBroadcastReceiver">
+            <intent-filter>
+                <action android:name="com.android.inputmethod.dictionarypack.UNKNOWN_CLIENT" />
+            </intent-filter>
+        </receiver>
+
         <provider android:name="com.android.inputmethod.dictionarypack.DictionaryProvider"
                   android:grantUriPermissions="true"
                   android:exported="false"
diff --git a/java/res/values-af/strings-appname.xml b/java/res/values-af/strings-appname.xml
deleted file mode 100644
index d6bb52f..0000000
--- a/java/res/values-af/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android-sleutelbord"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android-speltoetser"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android-sleutelbordinstellings"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Speltoets tans instellings"</string>
-</resources>
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 07b4503..f5a6245 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-sleutelbord (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-sleutelbord (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-sleutelbord-instellings (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-speltoetser (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android-speltoetserinstellings (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropsies"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Navorsing-loglêerbevele"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-speltoetser (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Soek kontakname op"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Speltoetser gebruik inskrywings uit jou kontaklys"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreer met sleuteldruk"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Steminvoer is gedeaktiveer"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Stel invoermetodes op"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Invoertale"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Stuur terugvoer"</string>
     <string name="select_language" msgid="3693815588777926848">"Invoertale"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak weer om te stoor"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordeboek beskikbaar"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Aktiveer gebruikerterugvoer"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Help hierdie invoermetode-redigeerder te verbeter deur gebruikstatistiek en omvalverslae outomaties na Google te stuur."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Sleutelbordtema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engels (VK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Nie nou nie"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Dieselfde invoerstyl bestaan ​​reeds: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Bruikbaarheidstudie-modus"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Sleutellangdrukvertraging-instellings"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Sleuteldruk se vibrasie-tydsduurinstellings"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Sleuteldruk se klankvolume-instellings"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lees eksterne woordeboeklêer"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Geen woordeboeklêers in die aflaaiselsvouer nie"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Kies \'n woordeboeklêer om te installeer"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Verstek"</string>
     <string name="language_settings" msgid="1671153053201809031">"Taal en invoer"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Kies invoermetode"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Woordeboekverskaffer"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Woordeboekverskaffer"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Woordeboek-diens"</string>
-    <string name="download_description" msgid="3274861514695032954">"Woordeboek se opdateerinligting"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Addisionele woordeboeke"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Woordeboek beskikbaar"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Instellings vir woordeboeke"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Gebruikerwoordeboeke"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Gebruikerwoordeboek"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Woordeboek beskikbaar"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Laai tans af"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Geïnstalleer"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Geïnstalleer, gedeaktiveer"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Kan nie aan woordeboekdiens koppel nie"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Geen woordeboeke beskikbaar nie"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Herlaai"</string>
-    <string name="last_update" msgid="3101549719827600346">"Laas opgedateer"</string>
-    <string name="message_updating" msgid="820186276704134720">"Kontroleer vir opdaterings"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Laai tans..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Hoofwoordeboek"</string>
-    <string name="cancel" msgid="5586531736609183304">"Kanselleer"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installeer"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Kanselleer aflaaisel"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Deaktiveer"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Aktiveer"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Vee uit"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Die gekose taal op jou mobiele toestel het \'n beskikbare woordeboek.&lt;br/&gt; Ons beveel aan dat die <xliff:g id="LANGUAGE">%1$s</xliff:g>-woordeboek &lt;b&gt;afgelaai&lt;/b&gt; word om jou tikervaring \'n beter een te maak.&lt;br/&gt; &lt;br/&gt; Dit kan \'n minuut of twee neem om oor 3G af te laai. Heffings mag geld as jy nie \'n &lt;b&gt;onbeperkte dataplan&lt;/b&gt;.&lt;br/&gt; het nie As jy onseker oor jou dataplan is, beveel ons aan dat jy \'n WiFi-verbinding soek om outomaties te begin aflaai.&lt;br/&gt; &lt;br/&gt; Wenk: Jy kan woordeboeke aflaai en verwyder deur te gaan na &lt;b&gt;Taal en invoer&lt;/b&gt; in die &lt;b&gt;Instellings&lt;/b&gt;-kieslys van jou mobiele toestel."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Laai nou af (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Laai oor Wi-Fi af"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"\'n Woordeboek is vir <xliff:g id="LANGUAGE">%1$s</xliff:g> beskikbaar"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Druk om te hersien en af ​​te laai"</string>
+    <string name="app_name" msgid="6320102637491234792">"Woordeboekverskaffer"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Woordeboekverskaffer"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Woordeboek-diens"</string>
+    <string name="download_description" msgid="6014835283119198591">"Woordeboek se opdateerinligting"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Voeg woordeboeke by"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Woordeboek beskikbaar"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Instellings vir woordeboeke"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Gebruikerwoordeboeke"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Gebruikerwoordeboek"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Woordeboek beskikbaar"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Laai tans af"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Geïnstalleer"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Geïnstalleer, gedeaktiveer"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Kan nie aan woordeboekdiens koppel nie"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Geen woordeboeke beskikbaar nie"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Verfris"</string>
+    <string name="last_update" msgid="730467549913588780">"Laas opgedateer"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Kontroleer vir opdaterings"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Laai tans…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Hoofwoordeboek"</string>
+    <string name="cancel" msgid="6830980399865683324">"Kanselleer"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installeer"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Kanselleer"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Vee uit"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Die gekose taal op jou mobiele toestel het \'n beskikbare woordeboek.&lt;br/&gt; Ons beveel aan dat die <xliff:g id="LANGUAGE">%1$s</xliff:g>-woordeboek &lt;b&gt;afgelaai&lt;/b&gt; word om jou tikervaring te verbeter.&lt;br/&gt; &lt;br/&gt; Dit kan \'n minuut of twee neem om oor 3G af te laai. Heffings kan dalk geld as jy nie \'n &lt;b&gt;onbeperkte dataplan&lt;/b&gt; het nie.&lt;br/&gt; As jy onseker oor jou dataplan is, beveel ons aan dat jy \'n Wi-Fi-verbinding soek om outomaties te begin aflaai.&lt;br/&gt; &lt;br/&gt; Wenk: Jy kan woordeboeke aflaai en verwyder deur te gaan na &lt;b&gt;Taal en invoer&lt;/b&gt; in die &lt;b&gt;Instellings&lt;/b&gt;-kieslys van jou mobiele toestel."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Laai nou af (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Laai oor Wi-Fi af"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"\'n Woordeboek is vir <xliff:g id="LANGUAGE">%1$s</xliff:g> beskikbaar"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Druk om te hersien en af te laai"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Laai tans af: voorstelle vir <xliff:g id="LANGUAGE">%1$s</xliff:g> sal binnekort gereed wees."</string>
 </resources>
diff --git a/java/res/values-am/strings-appname.xml b/java/res/values-am/strings-appname.xml
deleted file mode 100644
index fd93114..0000000
--- a/java/res/values-am/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"የAndroid ቁልፍ ሰሌዳ"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android የፊደል አራሚ"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android የቁልፍ ሰሌዳ ቅንብሮች"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"የፊደል አራሚ ቅንብሮች"</string>
-</resources>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 6f740a9..23add87 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"የAndroid ቁልፍ ሰሌዳ (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"የAndroid ቁልፍ ሰሌዳ (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"የAndroid ቁልፍ ሰሌዳ ቅንብሮች (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android ፊደል አራሚ (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"የAndroid ፊደል አራሚ ቅንብሮች (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"ግቤት አማራጮች"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"የጥናት የምዝግብ ማስታወሻ ትዕዛዞች"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android የፊደል ማረሚያ (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"የእውቅያ ስሞችን ተመልከት"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"ፊደል አራሚ ከእውቅያ ዝርዝርህ የገቡትን ይጠቀማል"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"በቁልፍመጫንጊዜ አንዝር"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"የድምፅ ግቤት ቦዝኗል"</string>
     <string name="configure_input_method" msgid="373356270290742459">"ግቤት ሜተዶችን አዋቀር"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ቋንቋዎች አግቤት"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"ግብረ-መልስ ላክ"</string>
     <string name="select_language" msgid="3693815588777926848">"ቋንቋዎች አግቤት"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ለማስቀመጥ እንደገና ንካ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"መዝገበ ቃላት አለ"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"የተጠቃሚ ግብረ ምላሽ አንቃ"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"ወደ Google የተሰናከለ ሪፖርቶች እና አጠቃቀም ስታስቲክስ በራስ ሰር በመላክ ይህን ግቤት ሜተድ አርትኢ እገዛ ያሻሽላል።"</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"የቁልፍ ሰሌዳ ገጽታ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"እንግሊዘኛ (የታላቋ ብሪታንያ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"እንግሊዘኛ (ዩ.ኤስ)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"አሁን አልፈልግም"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"ተመሳሳዩ የግብዓት ቅጥ አስቀድሞ አለ፦ <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"የተገልጋይነት ጥናት ሁነታ"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"የቁልፍ ረጅም ጭነት መዘግየት ቅንብሮች"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"ቁልፍ ተጫን በቅንጅቶች ወቅት ንዝረት"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"ቁልፍ ተጫን የድምጽ መጠን ቅንብሮች"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"ውጫዊ የመዝገበቃላት ፋይል አንብብ"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"በውርዶች አቃፊው ውስጥ ምንም የመዝገበ-ፋይሎች የሉም"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"የሚጭኑት የመዝገበ-ቃላት ፋይል ይምረጡ"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"ነባሪ"</string>
     <string name="language_settings" msgid="1671153053201809031">"ቋንቋ እና ግቤት"</string>
     <string name="select_input_method" msgid="4301602374609275003">"የግቤት ስልት ይምረጡ"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"መዝገበ ቃላት አቅራቢ"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"መዝገበ ቃላት አቅራቢ"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"የመዝገበ ቃላት አገልግሎት"</string>
-    <string name="download_description" msgid="3274861514695032954">"መዝገበ ቃላት ማዘመኛ መረጃ"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"እየታከሉ የሚያድጉ መዝገበ ቃላቶች"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"መዝገበ ቃላት ይገኛል"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"የመዝገበ ቃላት ቅንብሮች"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"የተጠቃሚ መዝገበ ቃላት"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"የተጠቃሚ መዝገበ ቃላት"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"መዝገበ ቃላት አለ"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"በአሁን ጊዜ በማውረድ ላይ"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"ተጭኗል"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"ተጭኗል፣ ተሰናክሏል"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"ወደ መዝገበ ቃላት አገልገሎት በማገናኘት ላይ ችግር"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"ምንም መዝገበ ቃላት የሉም"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"አድስ"</string>
-    <string name="last_update" msgid="3101549719827600346">"ለመጨረሻ ጊዜ የዘመነው"</string>
-    <string name="message_updating" msgid="820186276704134720">"ዝማኔዎችን በመፈተሽ ላይ"</string>
-    <string name="message_loading" msgid="8611339149825047446">"በመጫን ላይ…"</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"ዋና መዝገበ ቃል"</string>
-    <string name="cancel" msgid="5586531736609183304">"ተወው"</string>
-    <string name="install_dict" msgid="5525005524697607865">"ጫን"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"ማውረድን ተወው"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"አሰናክል"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"አንቃ"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"ሰርዝ"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"መዝገበ ቃላት ለ<xliff:g id="LANGUAGE">%1$s</xliff:g> ይገኛል"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"ለመገምገምና ለማውረድ ተጫን"</string>
+    <string name="app_name" msgid="6320102637491234792">"የመዝገበ-ቃላት አቅራቢ"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"የመዝገበ-ቃላት አቅራቢ"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"የመዝገበ-ቃላት አገልግሎት"</string>
+    <string name="download_description" msgid="6014835283119198591">"መዝገበ-ቃላት ዝማኔ መረጃ"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"ጭማሪ መዝገበ-ቃላት"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"መዝገበ-ቃላት ይገኛል"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"የመዝገበ-ቃላት ቅንብሮች"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"የተጠቃሚ መዝገበ-ቃላት"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"የተጠቃሚ መዝገበ-ቃላት"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"መዝገበ-ቃላት ይገኛል"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"በአሁን ጊዜ በመውረድ ላይ"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"ተጭኗል"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"ተጭኗል፣ ተሰናክሏል"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"ወደ መዝገበ-ቃላት አገልገሎት ማገናኘት ላይ ችግር"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"ምንም መዝገበ-ቃላት የሉም"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"አድስ"</string>
+    <string name="last_update" msgid="730467549913588780">"ለመጨረሻ ጊዜ የተዘመነው"</string>
+    <string name="message_updating" msgid="4457761393932375219">"ዝማኔዎችን በመፈለግ ላይ"</string>
+    <string name="message_loading" msgid="8689096636874758814">"በመጫን ላይ..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"ዋና መዝገበ-ቃላት"</string>
+    <string name="cancel" msgid="6830980399865683324">"ይቅር"</string>
+    <string name="install_dict" msgid="180852772562189365">"ጫን"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"ሰርዝ"</string>
+    <string name="delete_dict" msgid="756853268088330054">"ሰርዝ"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"ተንቀሳቃሽ መሣሪያዎ ላይ ለተመረጠው ቋንቋ የሚሆን መዝገበ-ቃላት ይገኛል።&lt;br/&gt; የትየባ ተሞክሮዎን ለማሻሻል የ<xliff:g id="LANGUAGE">%1$s</xliff:g> መዝገበ-ቃላቱን &lt;b&gt;እንዲያወርዱ&lt;/b&gt; እንመክራለን።&lt;br/&gt; &lt;br/&gt; ውርዱ በ3ጂ ላይ አንድ ወይም ሁለት ደቂቃ ሊወስድ ይችላል። &lt;b&gt;ያልተገደበ የውሂብ ዕቅድ&lt;/b&gt; ከሌለዎት ክፍያዎች መከፈል ሊኖርባቸው ይችላል።&lt;br/&gt; የትኛው የውሂብ ዕቅድ እንዳለዎት እርግጠኛ ካልሆኑ ውርዱን በራስ-ሰር ለመጀመር የWi-Fi ግንኙነት እንዲፈልጉ እንመክራለን።&lt;br/&gt; &lt;br/&gt; ጠቃሚ ምክር፦ የተንቀሳቃሽ መሣሪያዎ &lt;b&gt;ቅንብሮች&lt;/b&gt; ምናሌ ውስጥ ወዳለው &lt;b&gt;ቋንቋ እና ግብዓት&lt;/b&gt; በመሄድ መዝገበ-ቃላትን ማውረድና ማስወገድ ይችላሉ።"</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"አሁን አውርድ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> ሜባ)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"በWi-Fi አውርድ"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"መዝገበ-ቃላት ለ<xliff:g id="LANGUAGE">%1$s</xliff:g> ይገኛል"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"ለመገምገምና ለማውረድ ይጫኑ"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"በማውረድ ላይ፦ የ<xliff:g id="LANGUAGE">%1$s</xliff:g> ጥቆማ አስተያየቶች በቅርቡ ዝግጁ ይሆናሉ።"</string>
 </resources>
diff --git a/java/res/values-ar/strings-appname.xml b/java/res/values-ar/strings-appname.xml
deleted file mode 100644
index 3d81e5d..0000000
--- a/java/res/values-ar/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"لوحة مفاتيح Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"التدقيق الإملائي في Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"إعدادات لوحة مفاتيح Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"إعدادات التدقيق الإملائي"</string>
-</resources>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 5668d59..f364bcf 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"لوحة مفاتيح Android ‏(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"لوحة مفاتيح Android ‏(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"إعدادات لوحة مفاتيح Android‏ (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"المدقق الإملائي في Android‏ (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"إعدادات المدقق الإملائي في Android‏ (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"خيارات الإرسال"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"أوامر سجلات البحث"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"التدقيق الإملائي في Android‏ (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"بحث في أسماء جهات الاتصال"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"يستخدم المدقق الإملائي إدخالات من قائمة جهات الاتصال"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"اهتزاز عند ضغط مفتاح"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"الإدخال الصوتي مُعطل"</string>
     <string name="configure_input_method" msgid="373356270290742459">"تهيئة طرق الإدخال"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"لغات الإدخال"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"إرسال تعليقات"</string>
     <string name="select_language" msgid="3693815588777926848">"لغات الإدخال"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"المس مرة أخرى للحفظ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"القاموس متاح"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"تمكين ملاحظات المستخدم"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"المساعدة في تحسين محرر طريقة الإرسال هذا من خلال إرسال إحصاءات الاستخدام وتقارير الأعطال تلقائيًا إلى Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"مظهر لوحة المفاتيح"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"الإنجليزية (المملكة المتحدة)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"الإنجليزية (الولايات المتحدة)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"ليس الآن"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"نمط الإدخال ذاته موجود من قبل: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"وضع سهولة الاستخدام"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"إعدادات تأخير الضغط الطويل للمفاتيح"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"إعدادات مدة اهتزاز الضغط على المفاتيح"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"إعدادات مستوى صوت الضغط على المفاتيح"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"قراءة ملف قاموس خارجي"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"ليست هناك ملفات قواميس في مجلد التنزيلات"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"تحديد ملف قاموس للتثبيت"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"الافتراضية"</string>
     <string name="language_settings" msgid="1671153053201809031">"اللغة والإدخال"</string>
     <string name="select_input_method" msgid="4301602374609275003">"اختيار أسلوب الإدخال"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"مقدم القاموس"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"مقدم القاموس"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"خدمة القاموس"</string>
-    <string name="download_description" msgid="3274861514695032954">"معلومات تحديث القاموس"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"القواميس الإضافية"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"قاموس متوفر"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"إعدادات القواميس"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"قواميس المستخدم"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"قاموس المستخدم"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"القاموس متاح"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"يتم حاليًا التنزيل"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"مثبت"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"مثبت، معطل"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"مشكلة في الاتصال بخدمة القاموس"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"لا تتوفر أية قواميس"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"تحديث"</string>
-    <string name="last_update" msgid="3101549719827600346">"تاريخ آخر تحديث"</string>
-    <string name="message_updating" msgid="820186276704134720">"جارٍ البحث عن تحديثات"</string>
-    <string name="message_loading" msgid="8611339149825047446">"تحميل..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"القاموس الرئيسي"</string>
-    <string name="cancel" msgid="5586531736609183304">"إلغاء"</string>
-    <string name="install_dict" msgid="5525005524697607865">"تثبيت"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"إلغاء التنزيل"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"تعطيل"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"تمكين"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"حذف"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"هناك قاموس متوفر للغة <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"اضغط للمراجعة والتنزيل"</string>
+    <string name="app_name" msgid="6320102637491234792">"مقدم القاموس"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"مقدم القاموس"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"خدمة القاموس"</string>
+    <string name="download_description" msgid="6014835283119198591">"معلومات تحديث القاموس"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"القواميس الإضافية"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"القاموس متاح"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"إعدادات القواميس"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"قواميس المستخدم"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"قاموس المستخدم"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"القاموس متاح"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"يتم حاليًا التنزيل"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"تم التثبيت"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"مثبت، معطل"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"مشكلة في الاتصال بخدمة القاموس"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"لا تتوفر أية قواميس"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"تحديث"</string>
+    <string name="last_update" msgid="730467549913588780">"تاريخ آخر تحديث"</string>
+    <string name="message_updating" msgid="4457761393932375219">"جارٍ البحث عن تحديثات"</string>
+    <string name="message_loading" msgid="8689096636874758814">"جارٍ التحميل..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"القاموس الرئيسي"</string>
+    <string name="cancel" msgid="6830980399865683324">"إلغاء"</string>
+    <string name="install_dict" msgid="180852772562189365">"تثبيت"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"إلغاء"</string>
+    <string name="delete_dict" msgid="756853268088330054">"حذف"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"اللغة المحددة على جهازك الجوال تشتمل على قاموس متوفر.&lt;br/&gt; نوصي &lt;b&gt;بتنزيل&lt;/b&gt; قاموس <xliff:g id="LANGUAGE">%1$s</xliff:g> لتحسين تجربة الكتابة.&lt;br/&gt; &lt;br/&gt; قد يستغرق التنزيل دقيقة أو دقيقتين أكثر من المدة التي يستغرقها التنزيل عبر شبكة الجيل الثالث. قد تنطبق الرسوم إذا لم تكن مشتركًا في &lt;b&gt;خطة البيانات غير المحدودة&lt;/b&gt;.&lt;br/&gt; إذا لم تكن متأكدًا من خطة البيانات المتوفرة لديك، فنحن نوصي بالبحث عن اتصال Wi-Fi لبدء عملية التنزيل تلقائيًا.&lt;br/&gt; &lt;br/&gt; نصيحة: يمكنك تنزيل القواميس وإزالتها عن طريق الانتقال إلى &lt;b&gt;اللغة والإدخال&lt;/b&gt; في قائمة &lt;b&gt;إعدادات&lt;/b&gt; في جهازك الجوَّال."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"التنزيل الآن (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> ميغابايت)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"التنزيل عبر شبكة Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"هناك قاموس متوفر للغة <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"اضغط للمراجعة والتنزيل"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"جارٍ التنزيل: ستتوفر اقتراحات للغة <xliff:g id="LANGUAGE">%1$s</xliff:g> بعد قليل."</string>
 </resources>
diff --git a/java/res/values-be/strings-appname.xml b/java/res/values-be/strings-appname.xml
deleted file mode 100644
index e0aadfa..0000000
--- a/java/res/values-be/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Клавіятура Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Iнструмент праверкi правапiсу для Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Налады клавіятуры Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Налады праверкі арфаграфіі"</string>
-</resources>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index d12e47c..2d3fcfb 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавіятура Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавіятура Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Налады клавіятуры Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Iнструмент праверкi правапiсу для Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Налады інструмента праверкі правапісу для Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ўводу"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Каманды гiсторыя даследаванняў"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Iнструмент праверкi правапiсу для Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукаць імёны кантактаў"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Модуль праверкі правапісу выкарыстоўвае запісы са спісу кантактаў"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібрацыя пры націску клавіш"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Галасавы набор адкл."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Налада метадаў уводу"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Мовы ўводу"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Адправіць водгук"</string>
     <string name="select_language" msgid="3693815588777926848">"Мовы ўводу"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Дакраніцеся зноў, каб захаваць"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Слоўнік даступны"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Уключыць зваротную сувязь з карыстальнікамі"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Дапамажыце палепшыць гэты рэдактар ​​метаду ўводу, аўтаматычна адпраўляючы статыстыку выкарыстання і справаздачы аб збоях Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Тэма клавіятуры"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Англійская (ЗК)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Англійская (ЗША)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Не цяпер"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Такі метад уводу ўжо існуе: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Рэжым даследвання выкарыстальнасці"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Налады адмены доўгага нацiску клавiшы"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Налады працягласцi вiбрацыi пры нацiску"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Налады гучнасцi пры нацiску"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Чытанне знешняга файла слоўніка"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"У папцы загрузак няма файлаў слоўніка"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Вылучыце файл слоўніка для ўсталёўкі"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Па змаўчанні"</string>
     <string name="language_settings" msgid="1671153053201809031">"Мова і ўвод"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Выберыце метад уводу"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Пастаўшчык слоўніка"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Пастаўшчык слоўніка"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Слоўнік"</string>
-    <string name="download_description" msgid="3274861514695032954">"Інфармацыя абнаўлення слоўніка"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Дадатковыя слоўнікі"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Даступны слоўнік"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Налады для слоўнікаў"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Карыстальніцкія слоўнікі"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Карыстальніцкі слоўнік"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Даступны слоўнік"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Спампоўваецца зараз"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Усталяваны"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Усталявана, адключана"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Праблема падключэння да слоўніка"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Слоўнікаў няма"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Абнавіць"</string>
-    <string name="last_update" msgid="3101549719827600346">"Апошняе абнаўленне"</string>
-    <string name="message_updating" msgid="820186276704134720">"Праверка наяўнасці абнаўленняў"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Загрузка..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Асноўны слоўнік"</string>
-    <string name="cancel" msgid="5586531736609183304">"Адмена"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Усталяваць"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Адмяніць спампаванне"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Адключыць"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Уключыць"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Выдаліць"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Слоўнік для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\""</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Нацiснiце, каб прагледзець i спампаваць"</string>
+    <string name="app_name" msgid="6320102637491234792">"Пастаўшчык слоўніка"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Пастаўшчык слоўніка"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Слоўнік"</string>
+    <string name="download_description" msgid="6014835283119198591">"Інфармацыя абнаўлення слоўніка"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Дадатковыя слоўнікі"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Даступны слоўнік"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Налады для слоўнікаў"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Карыстальніцкія слоўнікі"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Карыстацкі слоўнік"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Даступны слоўнік"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Спампоўваецца зараз"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Усталявана"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Усталявана, адключана"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Праблема падключэння да слоўніка"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Слоўнікаў няма"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Абнавіць"</string>
+    <string name="last_update" msgid="730467549913588780">"Апошняе абнаўленне"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Праверка наяўнасці абнаўленняў"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Загрузка..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Асноўны слоўнік"</string>
+    <string name="cancel" msgid="6830980399865683324">"Адмяніць"</string>
+    <string name="install_dict" msgid="180852772562189365">"Усталяваць"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Адмена"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Выдаліць"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Для выбранай мовы на мабільнай прыладзе ёсць слоўнік.&lt;br/&gt; Мы рэкамендуем &lt;b&gt;спампаваць&lt;/b&gt; слоўнік для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\" для паляпшэння зручнасці набору.&lt;br/&gt; &lt;br/&gt; Спампоўка можа заняць хвіліну або дзве ў 3G-сетках. Калі ў вас няма &lt;b&gt;безлімітнага тарыфнага плану перадачы дадзеных&lt;/b&gt;, могуць прымяняцца дадатковыя плацяжы&lt;br/&gt;. Калі вы не ведаеце дакладна, які ў вас тарыфны план, мы рэкамендуем знайсці падлучэнне да сеткі Wi-Fi, каб пачаць аўтаматычную спампоўку.&lt;br/&gt; &lt;br/&gt; Парада: можна спампоўваць і выдаляць слоўнікі, перайшоўшы ў раздзел &lt;b&gt;Мова і ўвод&lt;/b&gt; у меню &lt;b&gt;Налады&lt;/b&gt; вашай мабільнай прылады."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Спампаваць зараз (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>МБ)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Спампаваць праз Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Слоўнік для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\""</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Нацiснiце, каб прагледзець i спампаваць"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Загрузка: прапановы для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\" хутка з\'явяцца."</string>
 </resources>
diff --git a/java/res/values-bg/strings-appname.xml b/java/res/values-bg/strings-appname.xml
deleted file mode 100644
index 49e301d..0000000
--- a/java/res/values-bg/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Клавиатура на Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Програма за правописна проверка за Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Настройки на клавиатурата на Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Настройки за проверка на правописа"</string>
-</resources>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 37eaa33..4862198 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавиатура на Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавиатура на Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Настройки на клавиатурата на Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Програма за правописна проверка за Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Настройки на програмата за правописна проверка за Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Опции за въвеждане"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Команди за рег. файл за проучвания"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Програма за правописна проверка за Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Търсене на имена"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"За проверка на правописа се ползват записи от списъка с контакти"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Да вибрира при натискане на клавиш"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Глас. въвежд. е деакт."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Конфигуриране на въвеждането"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Входни езици"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Изпращане на отзиви"</string>
     <string name="select_language" msgid="3693815588777926848">"Езици за въвеждане"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Докоснете отново, за да запазите"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Има достъп до речник"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Активиране на отзивите от потребителите"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Помогнете за подобряването на този редактор за въвеждане чрез автоматично изпращане до Google на статистически данни за употребата и сигнали за сривове."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема на клавиатурата"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"английски (Великобритания)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"английски (САЩ)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Не сега"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Същият стил на въвеждане вече съществува: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим за изучаване на използваемостта"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Настройки за забавяне при продължително натискане на клавишите"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки за продължителност на вибрирането при натискане на клавиш"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки за силата на звука при натискане на клавиш"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Четене на файл за външен речник"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"В папката „Изтегляния“ няма файлове за речник"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Изберете файл за речника, който да инсталирате"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Стандартни"</string>
     <string name="language_settings" msgid="1671153053201809031">"Език и въвеждане"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Избор на метод на въвеждане"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Доставчик на речника"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Доставчик на речника"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Услуга за речник"</string>
-    <string name="download_description" msgid="3274861514695032954">"Информация за актуализацията на речниците"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Добавени речници"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Налице е речник"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Настройки за речници"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Потребителски речници"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Потребителски речник"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Речникът е налице"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Изтеглят се понастоящем"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Инсталирано"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Инсталирано, деактивирано"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Има проблем с връзката"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Няма налични речници"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Опресняване"</string>
-    <string name="last_update" msgid="3101549719827600346">"Последна актуализация:"</string>
-    <string name="message_updating" msgid="820186276704134720">"Проверява се за актуализации"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Зарежда се..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Основен речник"</string>
-    <string name="cancel" msgid="5586531736609183304">"Отказ"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Инсталиране"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Анулиране на изтеглянето"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Деактивиране"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Активиране"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Изтриване"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"За <xliff:g id="LANGUAGE">%1$s</xliff:g> е налице речник"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Натиснете, за да прегледате и изтеглите"</string>
+    <string name="app_name" msgid="6320102637491234792">"Доставчик на речника"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Доставчик на речника"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Услуга за речник"</string>
+    <string name="download_description" msgid="6014835283119198591">"Информация за актуализацията на речниците"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Добавени речници"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Речникът е налице"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Настройки за речници"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Потребителски речници"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Потребителски речник"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Речникът е налице"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Понастоящем се изтегля"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Инсталиран"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Инсталиран, деактивиран"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Няма връзка с речниците"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Няма налични речници"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Опресняване"</string>
+    <string name="last_update" msgid="730467549913588780">"Последна актуализация:"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Проверява се за актуализации"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Зарежда се..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Основен речник"</string>
+    <string name="cancel" msgid="6830980399865683324">"Отказ"</string>
+    <string name="install_dict" msgid="180852772562189365">"Инсталиране"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Отказ"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Изтриване"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Налице е речник за избрания език на мобилното ви устройство.&lt;br/&gt; Препоръчваме ви &lt;b&gt;dда изтеглите&lt;/b&gt; речника за <xliff:g id="LANGUAGE">%1$s</xliff:g>, за да подобрите практическата си работа при писане.&lt;br/&gt; &lt;br/&gt; Изтеглянето през 3G може да отнеме една до две минути. Възможно е да бъдете таксувани, ако нямате &lt;b&gt;неограничен план за данни&lt;/b&gt;.&lt;br/&gt; В случай че не сте сигурни какъв е вашият план, ви препоръчваме да намерите Wi-Fi връзка, за да започнете автоматично изтеглянето.&lt;br/&gt; &lt;br/&gt; Съвет: Можете да изтегляте и премахвате речници, като отворите &lt;b&gt;Език и въвеждане&lt;/b&gt; в менюто &lt;b&gt;Настройки&lt;/b&gt; на мобилното си устройство."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Изтегляне сега (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> МБ)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Изтегляне през Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"За <xliff:g id="LANGUAGE">%1$s</xliff:g> е налице речник"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Натиснете, за да прегледате и изтеглите"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Изтегля се: Предложенията за <xliff:g id="LANGUAGE">%1$s</xliff:g> ще бъдат готови скоро."</string>
 </resources>
diff --git a/java/res/values-ca/strings-appname.xml b/java/res/values-ca/strings-appname.xml
deleted file mode 100644
index add5c3f..0000000
--- a/java/res/values-ca/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Teclat Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Corrector ortogràfic d\'Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Configuració del teclat d\'Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Configuració de la correcció ortogràfica"</string>
-</resources>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index c45b07c..93336c6 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclat d\'Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclat d\'Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Configuració del teclat d\'Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corrector ortogràfic d\'Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Configuració del corrector ortogràfic d\'Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opcions d\'entrada"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Recerca d\'ordres de reg."</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortogràfic d\'Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca noms de contactes"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortogràfic utilitza entrades de la llista de cont."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibra en prémer tecles"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. veu desactiv."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configura mètodes d\'entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomes d\'entrada"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Envia comentaris"</string>
     <string name="select_language" msgid="3693815588777926848">"Idiomes d\'entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Torna a tocar per desar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionari disponible"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Activa els comentaris de l\'usuari"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Ajuda a millorar aquest editor de mètodes d\'entrada enviant automàticament estadístiques d\'ús i informes de bloqueigs a Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclat"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglès (Regne Unit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglès (EUA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ara no"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ja existeix aquest estil d\'entrada: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'estudi d\'usabilitat"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Configuració del retard per mantenir premuda una tecla"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Configuració de durada de vibracions en prémer tecles"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Configuració del volum de so en prémer tecles"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lectura d\'un fitxer de diccionari extern"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No hi ha cap fitxer de diccionari a la carpeta Baixades"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecció d\'un fitxer de diccionari per instal·lar"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Predeterminat"</string>
     <string name="language_settings" msgid="1671153053201809031">"Idioma i introducció"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Selecció de mètodes d\'introducció"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Proveïdor de diccionaris"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Proveïdor de diccionaris"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Servei de diccionari"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informació d\'actualització del diccionari"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Diccionaris complementaris"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Diccionari disponible"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Configuració dels diccionaris"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Diccionaris de l\'usuari"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Diccionari de l\'usuari"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Diccionari disponible"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"S\'està baixant"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instal·lat"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instal·lat, desactivat"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"S\'ha produït un problema en connectar al servei de diccionari"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"No hi ha cap diccionari disponible."</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Actualitza"</string>
-    <string name="last_update" msgid="3101549719827600346">"Última actualització"</string>
-    <string name="message_updating" msgid="820186276704134720">"S\'està comprovant si hi ha actualitzacions"</string>
-    <string name="message_loading" msgid="8611339149825047446">"S\'està carregant..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Diccionari principal"</string>
-    <string name="cancel" msgid="5586531736609183304">"Cancel·la"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instal·la"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Cancel·la la baixada"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Desactiva"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Activa"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Suprimeix"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"L\'idioma seleccionat al teu dispositiu mòbil té un diccionari disponible.&lt;br/&gt; Et recomanem que &lt;b&gt;baixis&lt;/b&gt; el diccionari de <xliff:g id="LANGUAGE">%1$s</xliff:g> per millorar la teva experiència d\'escriptura.&lt;br/&gt; &lt;br/&gt; La baixada pot trigar un parell de minuts mitjançant 3G. És possible que s\'apliquin càrrecs si no tens un &lt;b&gt;pla de dades il·limitat&lt;/b&gt;.&lt;br/&gt; Si no estàs segur de quin pla de dades tens, et recomanem que cerquis una connexió Wi-Fi per començar la baixada automàticament.&lt;br/&gt; &lt;br/&gt; Consell: Pots baixar i eliminar diccionaris si vas a la secció &lt;b&gt;Idioma i entrada&lt;/b&gt; del menú &lt;b&gt;Configuració&lt;/b&gt; del dispositiu mòbil."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Baixa ara (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Baixa mitjançant Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Hi ha un diccionari disponible per a l\'idioma: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Prem per opinar i per baixar"</string>
+    <string name="app_name" msgid="6320102637491234792">"Proveïdor de diccionaris"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Proveïdor de diccionaris"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Servei de diccionari"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informació d\'actualització del diccionari"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Diccionaris complementaris"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Diccionari disponible"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Configuració dels diccionaris"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Diccionaris de l\'usuari"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Diccionari de l\'usuari"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Diccionari disponible"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"S\'està baixant"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instal·lat"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instal·lat, desactivat"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Error en connectar amb el diccionari"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Cap diccion. dispon."</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Actualitza"</string>
+    <string name="last_update" msgid="730467549913588780">"Última actualització"</string>
+    <string name="message_updating" msgid="4457761393932375219">"S\'està comprovant si hi ha actualitzacions"</string>
+    <string name="message_loading" msgid="8689096636874758814">"S\'està carregant..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Diccionari principal"</string>
+    <string name="cancel" msgid="6830980399865683324">"Cancel·la"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instal·la"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Cancel·la"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Suprimeix"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Hi ha un diccionari disponible per a l\'idioma seleccionat al teu dispositiu mòbil.&lt;br/&gt; Et recomanem que &lt;b&gt;baixis&lt;/b&gt; el diccionari de <xliff:g id="LANGUAGE">%1$s</xliff:g> per millorar la teva experiència d\'escriptura.&lt;br/&gt; &lt;br/&gt; La baixada pot trigar un parell de minuts en xarxes 3G. Si no tens un &lt;b&gt;pla de dades il·limitat&lt;/b&gt;.&lt;br/&amp;gt, és possible que s\'apliquin càrrecs. Si no estàs segur de les característiques del teu pla de dades, et recomanem que cerquis una connexió Wi-Fi per iniciar la baixada automàticament.&lt;br/&gt; &lt;br/&gt; Consell: Pots baixar i suprimir diccionaris a la secció &lt;b&gt;Idioma i entrada de text&lt;/b&gt; del menú &lt;b&gt;Configuració&lt;/b&gt; del dispositiu mòbil."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Baixa ara (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Baixa mitjançant Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Hi ha un diccionari disponible per a l\'idioma: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Prem per revisar-lo i per baixar-lo"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Baixada: els suggeriments per a <xliff:g id="LANGUAGE">%1$s</xliff:g> estaran disponibles ben aviat."</string>
 </resources>
diff --git a/java/res/values-cs/strings-appname.xml b/java/res/values-cs/strings-appname.xml
deleted file mode 100644
index 0eeac88..0000000
--- a/java/res/values-cs/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Klávesnice Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Kontrola pravopisu Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Nastavení klávesnice Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Nastavení kontroly pravopisu"</string>
-</resources>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 503ce1b..355d681 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klávesnice Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Klávesnice Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Nastavení klávesnice Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Kontrola pravopisu Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Nastavení kontroly pravopisu Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávání textu a dat"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Příkazy vývoj. protokolu"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhledat kontakty"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používá záznamy z vašeho seznamu kontaktů."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Při stisku klávesy vibrovat"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup vypnut"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurace metod zadávání"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Vstupní jazyky"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Odeslat zpětnou vazbu"</string>
     <string name="select_language" msgid="3693815588777926848">"Vstupní jazyky"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opětovným dotykem provedete uložení"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovník k dispozici"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Aktivovat zasílání statistik užívání a zpráv o selhání"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Automatickým zasíláním statistik o užívání editoru zadávání dat a zpráv o jeho selhání do Googlu můžete přispět k vylepšení tohoto nástroje."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Motiv klávesnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angličtina (Velká Británie)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angličtina (USA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Teď ne"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Tento styl zadávání již existuje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim studie použitelnosti"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Nastavení prodlevy dlouhého stisknutí kláves"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Délka vibrace při stisku klávesy"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Hlasitost při stisknutí klávesy"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Číst soubor externího slovníku"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Ve složce Stažené nejsou žádné soubory slovníků."</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Vyberte soubor slovníku k instalaci"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Výchozí"</string>
     <string name="language_settings" msgid="1671153053201809031">"Jazyk a zadávání"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Výběr metody zadávání dat"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Poskytovatel slovníku"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Poskytovatel slovníku"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Služba slovníku"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informace o aktualizaci slovníku"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Doplňkové slovníky"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Je k dispozici slovník"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Nastavení pro slovníky"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Uživatelské slovníky"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Uživatelský slovník"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"K dispozici je slovník"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Aktuální stahování"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Nainstalováno"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Nainstalováno, zakázáno"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Probl. s přip. k sl."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Žádné slovníky"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Aktualizovat"</string>
-    <string name="last_update" msgid="3101549719827600346">"Poslední aktualizace"</string>
-    <string name="message_updating" msgid="820186276704134720">"Kontrola aktualizací"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Načítání..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Hlavní slovník"</string>
-    <string name="cancel" msgid="5586531736609183304">"Zrušit"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Nainstalovat"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Zrušit stahování"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Zakázat"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Povolit"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Smazat"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Je k dispozici slovník pro jazyk <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Stisknutím zkontrolujete a stáhnete"</string>
+    <string name="app_name" msgid="6320102637491234792">"Poskytovatel slovníku"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Poskytovatel slovníku"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Služba slovníku"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informace o aktualizaci slovníku"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Doplňkové slovníky"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Slovník k dispozici"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Nastavení slovníků"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Uživatelské slovníky"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Uživatelský slovník"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Slovník k dispozici"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Aktuální stahování"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Nainstalováno"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Nainstalováno, zakázáno"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Chyba přip. k slovníku"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Žádné slovníky"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Aktualizovat"</string>
+    <string name="last_update" msgid="730467549913588780">"Poslední aktualizace"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Kontrola aktualizací"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Načítání..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Hlavní slovník"</string>
+    <string name="cancel" msgid="6830980399865683324">"Zrušit"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instalovat"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Zrušit"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Smazat"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Pro vybraný jazyk mobilního zařízení je k dispozici slovník.&lt;br/&gt; Doporučujeme slovník pro jazyk <xliff:g id="LANGUAGE">%1$s</xliff:g> &lt;b&gt;stáhnout&lt;/b&gt;. Usnadníte si tím zadávání textu.&lt;br/&gt; &lt;br/&gt; V síti 3G bude stahování chvíli trvat. Pokud nemáte &lt;b&gt;neomezený datový tarif&lt;/b&gt;, mohou vám být účtovány poplatky.&lt;br/&gt; Jestliže si nejste jisti, jaký datový tarif máte, doporučujeme vám najít připojení Wi-Fi. Stahování se pak zahájí automaticky.&lt;br/&gt; &lt;br/&gt; Tip: Slovníky můžete stahovat a odstraňovat v nabídce mobilního zařízení &lt;b&gt;Jazyk a vstup&lt;/b&gt; v &lt;b&gt;Nastavení&lt;/b&gt;."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Stáhnout ihned (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Stáhnout pouze přes Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Je k dispozici slovník pro jazyk <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Stisknutím zkontrolujete a stáhnete"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Stahování: návrhy pro jazyk <xliff:g id="LANGUAGE">%1$s</xliff:g> budou brzy k dispozici."</string>
 </resources>
diff --git a/java/res/values-da/strings-appname.xml b/java/res/values-da/strings-appname.xml
deleted file mode 100644
index faef582..0000000
--- a/java/res/values-da/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android-tastatur"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android-stavekontrol"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Indstillinger for Android-tastatur"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Indstillinger for stavekontrol"</string>
-</resources>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index af472f7..8b4ea07 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-tastatur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Indstillinger for Android-tastatur (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-stavekontrol (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Indstillinger for Android-stavekontrol (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Indstillinger for input"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Forskningslogkommandoer"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontrol (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå kontaktnavne op"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruger poster fra listen over kontaktpersoner"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibration ved tastetryk"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Stemmeinput deaktiveret"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inputmetoder"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Inputsprog"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Inputsprog"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Aktivér brugerfeedback"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Vær med til at forbedre denne inputmetode ved at sende anvendelsesstatistikker og rapporter om nedbrud til Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannien)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ikke nu"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Denne inputstil findes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tilstand for brugsstudie"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Forsinkelsesindstillinger for lange tastetryk"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Indstillinger for varighed af vibration ved tastetryk"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Indstillinger for lydstyrke ved tastetryk"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Læs ekstern ordbogsfil"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Der er ingen ordbogsfiler i mappen Downloads"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Vælg den ordbog, som du vil installere"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="language_settings" msgid="1671153053201809031">"Sprog og input"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Vælg inputmetode"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Dictionary Provider"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Dictionary Provider"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Ordbogstjeneste"</string>
-    <string name="download_description" msgid="3274861514695032954">"Opdateringsoplysninger for ordbøger"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Tillægsordbøger"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Der er en tilgængelig ordbog"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Indstillinger for ordbøger"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Brugerordbøger"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Brugerordbog"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Ordbog er tilgængelig"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Downloader i øjeblikket"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installeret"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installeret, deaktiveret"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Uden ordbogstjeneste"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Ingen tilg. ordbøger"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Opdater"</string>
-    <string name="last_update" msgid="3101549719827600346">"Sidst opdateret"</string>
-    <string name="message_updating" msgid="820186276704134720">"Søger efter opdateringer"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Indlæser..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Hovedordbog"</string>
-    <string name="cancel" msgid="5586531736609183304">"Annuller"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installer"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Annuller download"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Deaktiver"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Aktivér"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Slet"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Det valgte sprog på din mobilenhed har en tilgængelig ordbog.&lt;br/&gt; Vi anbefaler, at du  &lt;b&gt;downloader&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g>-ordbogen for at forbedre din skriveoplevelse.&lt;br/&gt; &lt;br/&gt; Downloaden kan tage 1-2 minutter via 3G. Der bliver muligvis opkrævet afgifter, hvis du ikke har et &lt;b&gt;ubegrænset dataabonnement&lt;/b&gt;.&lt;br/&gt;. Hvis du ikke er sikker på, hvilket dataabonnemt du har, anbefaler vi, at du finder en Wi-Fi-forbindelse for at starte automatisk download.&lt;br/&gt; &lt;br/&gt;Tip: Du kan downloade og fjerne ordbøger ved at gå til &lt;b&gt;Sprog og input &lt;/b&gt; i menuen &lt;b&gt;Indstillinger&lt;/b&gt; på din mobilenhed."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Download nu (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Download via Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Der er en tilgængelig ordbog for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Tryk for at gennemgå og downloade"</string>
+    <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Ordbogstjeneste"</string>
+    <string name="download_description" msgid="6014835283119198591">"Opdateringsoplysninger for ordbøger"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Tillægsordbøger"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Ordbog er tilgængelig"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Indstillinger for ordbøger"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Brugerordbøger"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Brugerordbog"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Ordbog er tilgængelig"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Downloader i øjeblikket"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installeret"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installeret, deaktiveret"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Ingen ordbogstjeneste"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Ingen tilg. ordbøger"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Opdater"</string>
+    <string name="last_update" msgid="730467549913588780">"Sidst opdateret"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Søger efter opdateringer"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Indlæser..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Hovedordbog"</string>
+    <string name="cancel" msgid="6830980399865683324">"Annuller"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installer"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Annuller"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Slet"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Det valgte sprog på din mobilenhed har en tilgængelig ordbog.&lt;br/&gt; Vi anbefaler, at du &lt;b&gt;downloader&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g>-ordbogen for at forbedre din skriveoplevelse.&lt;br/&gt; &lt;br/&gt; Downloaden kan tage 1-2 minutter via 3G. Der bliver muligvis opkrævet et gebyr, hvis du ikke har et &lt;b&gt;ubegrænset dataabonnement&lt;/b&gt;.&lt;br/&gt;. Hvis du ikke er sikker på, hvilket dataabonnement du har, anbefaler vi, at du finder en Wi-Fi-forbindelse for at starte automatisk download.&lt;br/&gt; &lt;br/&gt;Tip! Du kan downloade og fjerne ordbøger ved at gå til &lt;b&gt;Sprog og input &lt;/b&gt; i menuen &lt;b&gt;Indstillinger&lt;/b&gt; på din mobilenhed."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Download nu (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Download via Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Der er en tilgængelig ordbog for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Tryk for at gennemgå og downloade"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Downloader: Der vil snart være forslag klar på <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-de/strings-appname.xml b/java/res/values-de/strings-appname.xml
deleted file mode 100644
index fc5fb89..0000000
--- a/java/res/values-de/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android-Tastatur"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android-Rechtschreibprüfung"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android-Tastatureinstellungen"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Einstellungen für Rechtschreibprüfung"</string>
-</resources>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 7ef3d00..3f11379 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-Tastatur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-Tastatur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-Tastatureinstellungen (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-Rechtschreibprüfung (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Einstellungen für die Android-Rechtschreibprüfung (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Eingabeoptionen"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Forschungsprotokollbefehle"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-Rechtschreibprüfung (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktnamen prüfen"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rechtschreibprüfung kann Einträge aus meiner Kontaktliste verwenden"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Bei Tastendruck vibrieren"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spracheingabe deaktiviert"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Eingabemethoden konfigurieren"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Eingabesprachen"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Feedback geben"</string>
     <string name="select_language" msgid="3693815588777926848">"Eingabesprachen"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Zum Speichern erneut berühren"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfügbar"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Nutzer-Feedback aktivieren"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Tragen Sie zur Verbesserung dieses Eingabemethodeneditors bei, indem Sie automatisch Nutzungsstatistiken und Absturzberichte an Google senden."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturdesign"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Englisch (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Englisch (USA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Später"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Der gleiche Eingabestil ist bereits vorhanden: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Studie zur Benutzerfreundlichkeit"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Verzögerungseinstellungen für langen Tastendruck"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Vibrationsdauer bei Tastendruck"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Tonlautstärke bei Tastendruck"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Externe Wörterbuchdatei lesen"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Keine Wörterbuchdateien im Ordner \"Downloads\""</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Wörterbuchdatei zum Installieren auswählen"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="language_settings" msgid="1671153053201809031">"Sprache &amp; Eingabe"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Eingabemethode wählen"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Wörterbuchbereitstellung"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Wörterbuchbereitstellung"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Wörterbuch"</string>
-    <string name="download_description" msgid="3274861514695032954">"Update-Informationen für Wörterbuch"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Erweiterte Wörterbücher"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Wörterbuch verfügbar"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Einstellungen für Wörterbücher"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Meine Wörterbücher"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Mein Wörterbuch"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Wörterbuch verfügbar"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Aktuelle Downloads"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installiert"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installiert, deaktiviert"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Kein Wörterbuchdienst"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Keine Wörterbücher"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Aktualisieren"</string>
-    <string name="last_update" msgid="3101549719827600346">"Zuletzt aktualisiert"</string>
-    <string name="message_updating" msgid="820186276704134720">"Suche nach Updates..."</string>
-    <string name="message_loading" msgid="8611339149825047446">"Wird geladen..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Allgemeines Wörterbuch"</string>
-    <string name="cancel" msgid="5586531736609183304">"Abbrechen"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installieren"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Download abbrechen"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Deaktivieren"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Aktivieren"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Löschen"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Für die auf dem Mobilgerät ausgewählte Sprache ist ein Wörterbuch verfügbar.&lt;br/&gt; &lt;b&gt;Laden Sie das <xliff:g id="LANGUAGE">%1$s</xliff:g>-Wörterbuch herunter&lt;/b&gt; und verbessern Sie Ihre Eingabeerfahrung.&lt;br/&gt; &lt;br/&gt;Der Download über 3G kann ein bis zwei Minuten dauern. Falls Sie keine &lt;b&gt;Datenflatrate&lt;/b&gt; haben, fallen eventuell Gebühren an.&lt;br/&gt; Sollten Sie sich nicht sicher sein, welchen Datentarif Sie haben, suchen Sie eine WLAN-Verbindung, um den Download automatisch zu starten.&lt;br/&gt; &lt;br/&gt;Tipp: Im Menü &lt;b&gt;Einstellungen&lt;/b&gt; Ihres Mobilgeräts können Sie unter &lt;b&gt;Sprache &amp; Eingabe&lt;/b&gt; Wörterbücher herunterladen und entfernen."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Jetzt herunterladen (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Über WLAN herunterladen"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Es ist ein Wörterbuch für <xliff:g id="LANGUAGE">%1$s</xliff:g> verfügbar."</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Zum Lesen und Herunterladen drücken"</string>
+    <string name="app_name" msgid="6320102637491234792">"Wörterbuchbereitstellung"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Wörterbuchbereitstellung"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Wörterbuch"</string>
+    <string name="download_description" msgid="6014835283119198591">"Update-Informationen für Wörterbuch"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Erweiterte Wörterbücher"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Wörterbuch verfügbar"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Einstellungen für Wörterbücher"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Meine Wörterbücher"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Mein Wörterbuch"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Wörterbuch verfügbar"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Wird heruntergeladen..."</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installiert"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installiert, deaktiviert"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Kein Wörterbuchdienst"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Keine Wörterbücher"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Aktualisieren"</string>
+    <string name="last_update" msgid="730467549913588780">"Zuletzt aktualisiert"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Suche nach Updates..."</string>
+    <string name="message_loading" msgid="8689096636874758814">"Wird geladen..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Allgemeines Wörterbuch"</string>
+    <string name="cancel" msgid="6830980399865683324">"Abbrechen"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installieren"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Abbrechen"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Löschen"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Für die auf dem Mobilgerät ausgewählte Sprache ist ein Wörterbuch verfügbar.&lt;br/&gt; &lt;b&gt;Laden Sie das <xliff:g id="LANGUAGE">%1$s</xliff:g>-Wörterbuch herunter&lt;/b&gt; und verbessern Sie Ihre Eingabeerfahrung.&lt;br/&gt; &lt;br/&gt;Der Download über 3G kann ein bis zwei Minuten dauern. Falls Sie keine &lt;b&gt;Datenflatrate&lt;/b&gt; haben, fallen eventuell Gebühren an.&lt;br/&gt; Sollten Sie sich nicht sicher sein, welchen Datentarif Sie haben, suchen Sie eine WLAN-Verbindung, um den Download automatisch zu starten.&lt;br/&gt; &lt;br/&gt;Tipp: Im Menü &lt;b&gt;Einstellungen&lt;/b&gt; Ihres Mobilgeräts können Sie unter &lt;b&gt;Sprache &amp; Eingabe&lt;/b&gt; Wörterbücher herunterladen und entfernen."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Jetzt herunterladen (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Über WLAN herunterladen"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Es ist ein Wörterbuch für <xliff:g id="LANGUAGE">%1$s</xliff:g> verfügbar."</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Zum Lesen und Herunterladen drücken"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Download wurde gestartet: Vorschläge für <xliff:g id="LANGUAGE">%1$s</xliff:g> sind in Kürze bereit."</string>
 </resources>
diff --git a/java/res/values-el/strings-appname.xml b/java/res/values-el/strings-appname.xml
deleted file mode 100644
index a199655..0000000
--- a/java/res/values-el/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Πληκτρολόγιο Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Ορθογραφικός έλεγχος Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Ρυθμίσεις πληκτρολογίου Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Ρυθμίσεις ορθογραφικού ελέγχου"</string>
-</resources>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 74ffcf9..41cf098 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Πληκτρολόγιο Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Πληκτρολόγιο Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Ρυθμίσεις πληκτρολογίου Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Ορθογραφικός έλεγχος Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Ρυθμίσεις ορθογραφικού ελέγχου Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Επιλογές εισόδου"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Έρευνα εντολών καταγραφής"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Ορθογραφικός έλεγχος Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Αναζήτηση ονομάτων επαφών"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Ο ορθογρ. έλεγχος χρησιμοπ. καταχωρίσεις από τη λίστα επαφών σας"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Δόνηση κατά το πάτημα πλήκτρων"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Απεν. φωνητ. είσοδος"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Διαμόρφωση μεθόδων εισαγωγής"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Γλώσσες εισόδου"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Αποστολή σχολίων"</string>
     <string name="select_language" msgid="3693815588777926848">"Γλώσσες εισόδου"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Αγγίξτε ξανά για αποθήκευση"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Λεξικό διαθέσιμο"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Ενεργοποίηση σχολίων χρηστών"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Βοηθήστε μας να βελτιώσουμε αυτό το πρόγραμμα επεξεργασίας μεθόδου εισόδου στέλνοντας αυτόματα στατιστικά στοιχεία και αναφορές σφαλμάτων στην Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Θέμα πληκτρολογίου"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Αγγλικά (Η.Β.)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Αγγλικά (Η.Π.Α)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Όχι τώρα"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Το ίδιο στυλ εισόδου υπάρχει ήδη: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Λειτουργία μελέτης χρηστικότητας"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Ρυθμίσεις καθυστέρησης παρατεταμένου πατήματος πλήκτρου"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Ρυθμίσεις διάρκειας δόνησης κατά το πάτημα πλήκτρων"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Ρυθμίσεις έντασης ήχου κατά το πάτημα πλήκτρων"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ανάγνωση εξωτερικού αρχείου λεξικού"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Δεν υπάρχουν αρχεία λεξικού στο φάκελο \"Λήψεις\""</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Επιλογή αρχείου λεξικού για εγκατάσταση"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Προεπιλογή"</string>
     <string name="language_settings" msgid="1671153053201809031">"Γλώσσα και εισαγωγή"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Επιλογή μεθόδου εισαγωγής"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Παροχέας λεξικού"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Παροχέας λεξικού"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Υπηρεσία λεξικού"</string>
-    <string name="download_description" msgid="3274861514695032954">"Ενημέρωση πληροφοριών λεξικού"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Πρόσθετα λεξικά"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Διαθέσιμο λεξικό"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Ρυθμίσεις για λεξικά"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Λεξικά χρήστη"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Λεξικό χρήστη"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Διαθέσιμο λεξικό"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Λήψη αυτήν τη στιγμή"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Εγκατεστημένο"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Εγκαταστάθηκε, απενεργοποιήθηκε"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Πρόβλ.σύνδ.στο λεξ."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Δεν υπάρχουν διαθέσιμα λεξικά"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Ανανέωση"</string>
-    <string name="last_update" msgid="3101549719827600346">"Τελευταία ενημέρωση"</string>
-    <string name="message_updating" msgid="820186276704134720">"Έλεγχος για ενημερώσεις"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Φόρτωση..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Κύριο λεξικό"</string>
-    <string name="cancel" msgid="5586531736609183304">"Ακύρωση"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Εγκατάσταση"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Ακύρωση λήψης"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Απενεργοποίηση"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Ενεργοποίηση"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Διαγραφή"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Υπάρχει διαθέσιμο λεξικό για τα <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Πατήστε για έλεγχο και λήψη"</string>
+    <string name="app_name" msgid="6320102637491234792">"Παροχέας λεξικού"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Παροχέας λεξικού"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Υπηρεσία λεξικού"</string>
+    <string name="download_description" msgid="6014835283119198591">"Ενημέρωση πληροφοριών λεξικού"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Πρόσθετα λεξικά"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Διαθέσιμο λεξικό"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Ρυθμίσεις για λεξικά"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Λεξικά χρήστη"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Λεξικό χρήστη"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Διαθέσιμο λεξικό"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Λήψη αυτήν τη στιγμή"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Εγκαταστάθηκε"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Εγκαταστάθηκε, απενεργοποιήθηκε"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Πρόβλ. σύνδ. στο λεξικό."</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Δεν υπάρχουν λεξικά"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Ανανέωση"</string>
+    <string name="last_update" msgid="730467549913588780">"Τελευταία ενημέρωση"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Έλεγχος για ενημερώσεις"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Φόρτωση…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Κύριο λεξικό"</string>
+    <string name="cancel" msgid="6830980399865683324">"Ακύρωση"</string>
+    <string name="install_dict" msgid="180852772562189365">"Εγκατάσταση"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Ακύρωση"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Διαγραφή"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Η επιλ. γλώσσα στην κιν. συσκευή σας διαθέτει λεξικό.&lt;br/&gt; Προτείνουμε να &lt;b&gt;κάνετε λήψη&lt;/b&gt; του λεξικού <xliff:g id="LANGUAGE">%1$s</xliff:g> για να βελτ. την πληκτρολόγηση.&lt;br/&gt; &lt;br/&gt; Για τη λήψη μπορεί να χρειαστούν 1 ή 2 λεπτά μέσω 3G. Ίσως ισχύουν χρεώσεις αν δεν έχετε &lt;b&gt;πρόγρ. απερ. δεδομ.&lt;/b&gt;.&lt;br/&gt; Αν δεν γνωρίζετε ποιο πρόγ. δεδ. έχετε, προτείνουμε να βρείτε μια σύνδ. Wi-Fi για να ξεκιν. αυτόμ. η λήψη.&lt;br/&gt; &lt;br/&gt; Συμβουλή: Μπορείτε να λάβετε και να καταργ. λεξικά, από την περιοχή &lt;b&gt;Γλώσσα και εισαγωγή&lt;/b&gt;, στο μενού &lt;b&gt;Ρυθμίσεις&lt;/b&gt; της κιν. συσκ."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Άμεση λήψη (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Λήψη μέσω Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Υπάρχει διαθέσιμο λεξικό για τα <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Πατήστε για έλεγχο και λήψη"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Λήψη: Οι προτάσεις για τα <xliff:g id="LANGUAGE">%1$s</xliff:g> θα είναι έτοιμες σύντομα."</string>
 </resources>
diff --git a/java/res/values-en-rGB/strings-appname.xml b/java/res/values-en-rGB/strings-appname.xml
deleted file mode 100644
index ad9e782..0000000
--- a/java/res/values-en-rGB/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android keyboard"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android spell checker"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android keyboard settings"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Spell checking settings"</string>
-</resources>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 3bb7bab..3aab692 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android Keyboard (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android Keyboard Settings (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android Spell Checker (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android Spell Checker Settings (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android spell checker (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Look up contact names"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Spell checker uses entries from your contact list"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on key-press"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Voice input is disabled"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Input languages"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Enable user feedback"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Help improve this input method editor by sending usage statistics and crash reports automatically to Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Not now"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"The same input style already exists: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Usability study mode"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Key long press delay settings"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Key-press vibration duration settings"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Key-press sound volume settings"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Read external dictionary file"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No dictionary files in the Downloads folder"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Select a dictionary file to install"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Default"</string>
     <string name="language_settings" msgid="1671153053201809031">"Language &amp; input"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Choose input method"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Dictionary Provider"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Dictionary Provider"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Dictionary Service"</string>
-    <string name="download_description" msgid="3274861514695032954">"Dictionary update information"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Add-on dictionaries"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dictionary available"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Settings for dictionaries"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"User dictionaries"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"User dictionary"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Dictionary available"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Currently downloading"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installed"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installed, disabled"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problem while connecting to dictionary service"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"No dictionaries available"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Refresh"</string>
-    <string name="last_update" msgid="3101549719827600346">"Last updated"</string>
-    <string name="message_updating" msgid="820186276704134720">"Checking for updates"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Loading..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Main dictionary"</string>
-    <string name="cancel" msgid="5586531736609183304">"Cancel"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Install"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Cancel download"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Disable"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Enable"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Delete"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"The selected language on your mobile device has an available dictionary.&lt;br/&gt; We recommend &lt;b&gt;downloading&lt;/b&gt; the <xliff:g id="LANGUAGE">%1$s</xliff:g> dictionary to improve your typing experience.&lt;br/&gt; &lt;br/&gt; The download could take a minute or two over 3G. Charges may apply if you don\'t have an &lt;b&gt;unlimited data plan&lt;/b&gt;.&lt;br/&gt; If you are not sure which data plan you have, we recommend finding a Wifi connection to start the download automatically.&lt;br/&gt; &lt;br/&gt; Tip: You can download and remove dictionaries by going to &lt;b&gt;Language &amp; input&lt;/b&gt; in the &lt;b&gt;Settings&lt;/b&gt; menu of your mobile device."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Download now (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Download over Wifi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"A dictionary is available for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Press to review and download"</string>
+    <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Dictionary Service"</string>
+    <string name="download_description" msgid="6014835283119198591">"Dictionary update information"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Add-on dictionaries"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dictionary available"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Settings for dictionaries"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"User dictionaries"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"User dictionary"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dictionary available"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Currently downloading"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installed"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installed, disabled"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Problem connecting to dictionary service"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"No dictionaries available"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Refresh"</string>
+    <string name="last_update" msgid="730467549913588780">"Last updated"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Checking for updates"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Loading..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Main dictionary"</string>
+    <string name="cancel" msgid="6830980399865683324">"Cancel"</string>
+    <string name="install_dict" msgid="180852772562189365">"Install"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Cancel"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Delete"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"The selected language on your mobile device has an available dictionary.&lt;br/&gt; We recommend &lt;b&gt;downloading&lt;/b&gt; the <xliff:g id="LANGUAGE">%1$s</xliff:g> dictionary to improve your typing experience.&lt;br/&gt; &lt;br/&gt; The download could take a minute or two over 3G. Charges may apply if you don\'t have an &lt;b&gt;unlimited data plan&lt;/b&gt;.&lt;br/&gt; If you are not sure which data plan you have, we recommend finding a Wi-Fi connection to start the download automatically.&lt;br/&gt; &lt;br/&gt; Tip: You can download and remove dictionaries by going to &lt;b&gt;Language &amp; input&lt;/b&gt; in the &lt;b&gt;Settings&lt;/b&gt; menu of your mobile device."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Download now (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Download over Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"A dictionary is available for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Press to review and download"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Downloading: suggestions for <xliff:g id="LANGUAGE">%1$s</xliff:g> will be ready soon."</string>
 </resources>
diff --git a/java/res/values-es-rUS/strings-appname.xml b/java/res/values-es-rUS/strings-appname.xml
deleted file mode 100644
index 5f08afb..0000000
--- a/java/res/values-es-rUS/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Teclado de Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Corrector ortográfico de Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Configuración de teclado de Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Configuración del corrector ortográfico"</string>
-</resources>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 0d0aa14..6fe85f1 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado de Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado de Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Configuración del teclado de Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corrector ortográfico de Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Configuración del corrector ortográfico de Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones de entrada"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro invest."</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortográfico de Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres contactos"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortográfico usa entradas de tu lista de contactos."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar teclas"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"La entrada por voz está inhabilitada"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentarios"</string>
     <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Vuelve a tocar para guardar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Activar los comentarios del usuario"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de introducción de texto al enviar las estadísticas de uso y los informes de error a Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglés (EE.UU.)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ahora no"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ya existe el estilo de entrada <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudio de usabilidad"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Configuración de retraso de presión prolongada"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Duración de vibración al presionar teclas"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volumen de sonido al presionar teclas"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Leer archivo de diccionario externo"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No hay archivos de diccionario en la carpeta de descargas."</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Seleccionar archivo de diccionario para instalar"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Predeterminado"</string>
     <string name="language_settings" msgid="1671153053201809031">"Teclado e idioma"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Seleccionar método de entrada"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Proveedor de diccionarios"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Proveedor de diccionarios"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Servicio de diccionarios"</string>
-    <string name="download_description" msgid="3274861514695032954">"Información acerca de la actualización del diccionario"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Diccionarios complementarios"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Diccionario disponible"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Configuración de los diccionarios"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Diccionarios del usuario"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Diccionario del usuario"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Diccionario disponible"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Descarga en curso"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instalado"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instalado, inhabilitado"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Err. conex. con dic."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"No hay diccionarios."</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Actualizar"</string>
-    <string name="last_update" msgid="3101549719827600346">"Última actualización"</string>
-    <string name="message_updating" msgid="820186276704134720">"Buscando las actualizaciones"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Cargando…"</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Diccionario principal"</string>
-    <string name="cancel" msgid="5586531736609183304">"Cancelar"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instalar"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Cancelar la descarga"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Inhabilitar"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Activar"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Eliminar"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Hay un diccionario disponible para el idioma seleccionado en tu dispositivo móvil.&lt;br/&gt; Te recomendamos que &lt;b&gt;descargues&lt;/b&gt; el diccionario de <xliff:g id="LANGUAGE">%1$s</xliff:g> para mejorar tu experiencia de escritura.&lt;br/&gt; &lt;br/&gt; La descarga puede tardar unos minutos en redes 3G. Si no tienes un &lt;b&gt;plan de datos ilimitado&lt;/b&gt;, es posible que se apliquen cargos.&lt;br/&gt; Si no conoces las características de tu plan de datos, te recomendamos que uses una conexión Wi-Fi para iniciar la descarga automáticamente.&lt;br/&gt; &lt;br/&gt; Sugerencia: Puedes descargar y eliminar diccionarios en la sección &lt;b&gt;Idioma e introducción de texto&lt;/b&gt; del menú &lt;b&gt;Ajustes&lt;/b&gt; del dispositivo móvil."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Descargar ahora ( <xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Descargar mediante Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Hay un diccionario disponible de <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Pulsa para consultar y descargar"</string>
+    <string name="app_name" msgid="6320102637491234792">"Proveedor de diccionarios"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Proveedor de diccionarios"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Servicio de diccionarios"</string>
+    <string name="download_description" msgid="6014835283119198591">"Información acerca de la actualización de diccionarios"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Diccionarios complementarios"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Diccionario disponible"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Configuración para diccionarios"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Diccionarios del usuario"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Diccionario del usuario"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Diccionario disponible"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Descargando actualmente"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instalado"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instalado, inhabilitado"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Err. conex. con dic."</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"No hay diccionarios."</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Actualizar"</string>
+    <string name="last_update" msgid="730467549913588780">"Última actualización"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Buscando actualizaciones"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Cargando..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Diccionario principal"</string>
+    <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instalar"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Cancelar"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Eliminar"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Hay un diccionario disponible para el idioma seleccionado en tu dispositivo móvil.&lt;br/&gt; Te recomendamos que &lt;b&gt;descargues&lt;/b&gt; el diccionario de <xliff:g id="LANGUAGE">%1$s</xliff:g> para mejorar tu experiencia de escritura.&lt;br/&gt; &lt;br/&gt; La descarga puede tardar unos minutos en redes 3G. Si no tienes un &lt;b&gt;plan de datos ilimitado&lt;/b&gt;, es posible que se apliquen cargos.&lt;br/&gt; Si no conoces las características de tu plan de datos, te recomendamos que uses una conexión Wi-Fi para iniciar la descarga automáticamente.&lt;br/&gt; &lt;br/&gt; Sugerencia: Puedes descargar y eliminar diccionarios en la sección &lt;b&gt;Teclado e idioma&lt;/b&gt; del menú &lt;b&gt;Configuración&lt;/b&gt; del dispositivo móvil."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Descargar ahora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Descargar por Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Hay un diccionario disponible de <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Pulsar para opinar y descargar"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Descargando: las sugerencias de <xliff:g id="LANGUAGE">%1$s</xliff:g> estarán disponibles en breve."</string>
 </resources>
diff --git a/java/res/values-es/strings-appname.xml b/java/res/values-es/strings-appname.xml
deleted file mode 100644
index cce9a17..0000000
--- a/java/res/values-es/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Teclado de Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Corrector ortográfico de Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Ajustes del teclado de Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Ajustes del corrector ortográfico"</string>
-</resources>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 95846ef..f02cb93 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Ajustes del teclado de Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corrector de Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Ajustes del corrector de Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones entrada texto"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro investigación"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector de Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Nombres de contactos"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Añadir nombres de tu lista de contactos al corrector"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar tecla"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entrada de voz inhabilitada"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Danos tu opinión"</string>
     <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca otra vez para guardar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Habilitar comentarios de usuarios"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de entrada de texto enviando estadísticas de uso e informes de error a Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema de teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"inglés (EE.UU.)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ahora no"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ya existe el estilo de entrada <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo estudio de usabilidad"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Ajustes de retraso de pulsación prolongada"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Duración de la vibración al pulsar tecla"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volumen sonido al pulsar tecla"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Leer archivo de diccionario externo"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No hay archivos de diccionario en la carpeta de descargas."</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecciona un archivo de diccionario para instalar"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Predeterminado"</string>
     <string name="language_settings" msgid="1671153053201809031">"Idioma y entrada de texto"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Selecciona un método de entrada"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Proveedor del diccionario"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Proveedor del diccionario"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Servicio de diccionario"</string>
-    <string name="download_description" msgid="3274861514695032954">"Información de actualización del diccionario"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Diccionarios complementarios"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Diccionario disponible"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Ajustes de diccionarios"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Diccionarios del usuario"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Diccionario del usuario"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Hay un diccionario disponible"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Descargas en curso"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instalado"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instalado (inhabilitado)"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Error al conectar"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"No hay diccionarios"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Actualizar"</string>
-    <string name="last_update" msgid="3101549719827600346">"Última actualización"</string>
-    <string name="message_updating" msgid="820186276704134720">"Buscando actualizaciones"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Cargando..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Diccionario principal"</string>
-    <string name="cancel" msgid="5586531736609183304">"Cancelar"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instalar"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Cancelar descarga"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Inhabilitar"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Habilitar"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Eliminar"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Hay un diccionario disponible para el idioma seleccionado en tu dispositivo móvil.&lt;br/&gt; Te recomendamos que &lt;b&gt;descargues&lt;/b&gt; el diccionario de <xliff:g id="LANGUAGE">%1$s</xliff:g> para mejorar tu experiencia de escritura.&lt;br/&gt; &lt;br/&gt; La descarga puede tardar unos minutos en redes 3G. Si no tienes un &lt;b&gt;plan de datos ilimitado&lt;/b&gt;, es posible que se apliquen cargos.&lt;br/&gt; Si no conoces las características de tu plan de datos, te recomendamos que uses una conexión Wi-Fi para iniciar la descarga automáticamente.&lt;br/&gt; &lt;br/&gt; Sugerencia: puedes descargar y eliminar diccionarios en la sección &lt;b&gt;Idioma e introducción de texto&lt;/b&gt; del menú &lt;b&gt;Ajustes&lt;/b&gt; del dispositivo móvil."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Descargar ahora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Descargar mediante Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Hay un diccionario disponible de <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Pulsa para comprobar y descargar"</string>
+    <string name="app_name" msgid="6320102637491234792">"Proveedor del diccionario"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Proveedor del diccionario"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Servicio de diccionario"</string>
+    <string name="download_description" msgid="6014835283119198591">"Información de actualización del diccionario"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Diccionarios complementarios"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Diccionario disponible"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Ajustes de diccionarios"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Diccionarios del usuario"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Diccionario del usuario"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Diccionario disponible"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Descargando..."</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instalado"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instalado (inhabilitado)"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Error al conectar"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"No hay diccionarios"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Actualizar"</string>
+    <string name="last_update" msgid="730467549913588780">"Última actualización"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Buscando actualizaciones"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Cargando..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Diccionario principal"</string>
+    <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instalar"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Cancelar"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Eliminar"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Hay un diccionario disponible para el idioma seleccionado en tu dispositivo móvil.&lt;br/&gt; Te recomendamos que &lt;b&gt;descargues&lt;/b&gt; el diccionario de <xliff:g id="LANGUAGE">%1$s</xliff:g> para mejorar tu experiencia de escritura.&lt;br/&gt; &lt;br/&gt; La descarga puede tardar unos minutos en redes 3G. Si no tienes un &lt;b&gt;plan de datos ilimitado&lt;/b&gt;, se pueden aplicar cargos.&lt;br/&gt; Si no conoces las características de tu plan de datos, te recomendamos que uses una conexión Wi-Fi para iniciar la descarga automáticamente.&lt;br/&gt; &lt;br/&gt; Sugerencia: puedes descargar y eliminar diccionarios en la sección &lt;b&gt;Idioma y entrada de texto&lt;/b&gt; del menú &lt;b&gt;Ajustes&lt;/b&gt; del dispositivo móvil."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Descargar ahora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Descargar mediante Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Hay un diccionario disponible de <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Pulsa para comprobar y descargar"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Descargando: las sugerencias de <xliff:g id="LANGUAGE">%1$s</xliff:g> estarán disponibles en breve."</string>
 </resources>
diff --git a/java/res/values-et/strings-appname.xml b/java/res/values-et/strings-appname.xml
deleted file mode 100644
index 181d597..0000000
--- a/java/res/values-et/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Androidi klaviatuur"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Androidi õigekirjakontroll"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Androidi klaviatuuri seaded"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Õigekirjakontrolli seaded"</string>
-</resources>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index 0697cab..9d5db66 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-klaviatuur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androidi klaviatuur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Androidi klaviatuuri seaded (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidi õigekirjakontroll (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Androidi õigekirjakontrolli seaded (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Sisestusvalikud"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Uuringulogi käsud"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidi õigekirjakontroll (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontakti nimede kontroll."</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Õigekirjakontroll kasutab teie kontaktisikute loendi sissekandeid"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreeri klahvivajutusel"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Kõnesisend on keelatud"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Sisestusmeetodite seadistamine"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Sisestuskeeled"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Saatke tagasisidet"</string>
     <string name="select_language" msgid="3693815588777926848">"Sisestuskeeled"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Salvestamiseks puudutage uuesti"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sõnastik saadaval"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Luba kasutaja tagasiside"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Saatke Google\'ile automaatselt kasutusstatistikat ja krahhiaruandeid ning aidake seda sisestusmeetodi redigeerijat parandada."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatuuri teema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglise (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglise (USA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Mitte kohe"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sama sisendstiil on juba olemas: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kasutatavuse uurimisrežiim"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Pika klahvivajutuse viivituse seaded"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Klahvivajutuse vibratsiooni kestuse seaded"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Klahvivajutuse helitugevuse seaded"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Välise sõnastikufaili lugemine"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Kaustas Allalaadimised pole ühtegi sõnastikufaili"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Installitava sõnastikufaili valimine"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Vaikeväärtus"</string>
     <string name="language_settings" msgid="1671153053201809031">"Keeled ja sisestamine"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Valige sisestusmeetod"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Sõnastikupakkuja"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Sõnastikupakkuja"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Sõnaraamatuteenus"</string>
-    <string name="download_description" msgid="3274861514695032954">"Sõnastiku värskendamisteave"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Pistiksõnastikud"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Sõnastik on saadaval"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Sõnastike seaded"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Kasutajasõnastikud"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Kasutajasõnastik"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Sõnastik on saadaval"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Praegu allalaadimisel"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installitud"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installitud, keelatud"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Tõrge sõnast. ühend."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Sõnastikke pole"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Värskenda"</string>
-    <string name="last_update" msgid="3101549719827600346">"Viimati värskendatud"</string>
-    <string name="message_updating" msgid="820186276704134720">"Värskenduste otsimine"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Laadimine ..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Põhisõnastik"</string>
-    <string name="cancel" msgid="5586531736609183304">"Tühista"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installi"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Tühista allalaadimine"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Keela"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Luba"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Kustuta"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Mobiilseadmes valitud keelele on saadaval sõnastik.&lt;br/&gt; Teksti sisestamiseks  soovitame &lt;b&gt;alla laadida&lt;/b&gt; sõnastiku <xliff:g id="LANGUAGE">%1$s</xliff:g>.&lt;br/&gt; &lt;br/&gt; 3G kaudu allalaadimisele võib kuluda minut või paar. Kehtida võivad tasud, kui te ei kasuta &lt;b&gt;piiramatut andmepaketti&lt;/b&gt;.&lt;br/&gt; Kui te ei tea, millist andmepaketti kasutate, soovitame allalaadimise automaatseks käivitamiseks leida WiFi-ühenduse.&lt;br/&gt; &lt;br/&gt; Nõuanne: sõnastikke saate alla laadida ja eemaldada, tehes valiku &lt;b&gt;Keele &amp; sisend&lt;/b&gt; mobiilseadme menüüs &lt;b&gt;Seaded&lt;/b&gt;."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Laadi kohe alla (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Laadi alla WiFi kaudu"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Sõnastik on <xliff:g id="LANGUAGE">%1$s</xliff:g> keele jaoks saadaval"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Vajutage ülevaatamiseks ja allalaadimiseks"</string>
+    <string name="app_name" msgid="6320102637491234792">"Sõnastikupakkuja"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Sõnastikupakkuja"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Sõnastikuteenus"</string>
+    <string name="download_description" msgid="6014835283119198591">"Sõnastiku värskendamisteave"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Pistiksõnastikud"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Sõnastik on saadaval"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Sõnastike seaded"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Kasutaja sõnastikud"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Kasutaja sõnastik"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Sõnastik on saadaval"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Praegu allalaadimisel"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installitud"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installitud, keelatud"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Probleem sõnastikuga ühendumisel"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Sõnastikke pole"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Värskenda"</string>
+    <string name="last_update" msgid="730467549913588780">"Viimati värskendatud"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Värskenduste otsimine"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Laadimine ..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Peamine sõnastik"</string>
+    <string name="cancel" msgid="6830980399865683324">"Tühista"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installi"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Tühista"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Kustuta"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Mobiilseadmes valitud keelele on saadaval sõnastik.&lt;br/&gt; Teksti mugavamaks sisestamiseks soovitame &lt;b&gt;alla laadida&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> keele sõnastiku.&lt;br/&gt; &lt;br/&gt; 3G kaudu allalaadimisele võib kuluda minut või paar. Kehtida võivad tasud, kui te ei kasuta &lt;b&gt;piiramatut andmepaketti&lt;/b&gt;.&lt;br/&gt; Kui te ei tea, millist andmepaketti kasutate, soovitame allalaadimise automaatseks käivitamiseks leida WiFi-ühenduse.&lt;br/&gt; &lt;br/&gt; Nõuanne: sõnastikke saate alla laadida ja eemaldada, tehes valiku &lt;b&gt;Keel ja sisestamine&lt;/b&gt; mobiilseadme menüüs &lt;b&gt;Seaded&lt;/b&gt;."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Laadi kohe alla (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Laadi alla WiFi kaudu"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Sõnastik on <xliff:g id="LANGUAGE">%1$s</xliff:g> keele jaoks saadaval"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Vajutage ülevaatamiseks ja allalaadimiseks"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Allalaadimine: <xliff:g id="LANGUAGE">%1$s</xliff:g> keele soovitused on varsti saadaval."</string>
 </resources>
diff --git a/java/res/values-fa/strings-appname.xml b/java/res/values-fa/strings-appname.xml
deleted file mode 100644
index ba2a76f..0000000
--- a/java/res/values-fa/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"صفحه‌کلید Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"غلط‌گیر املای Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"تنظیمات صفحه‌کلید Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"تنظیمات غلط‌‌ گیر املا"</string>
-</resources>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index ecc7e28..3171e17 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"صفحه‌کلید (Android (AOSP"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"صفحه کلید Android ‏(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"تنظیمات صفحه کلید Android ‏(AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"غلط‌گیر Android ‏(AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"تنظیمات غلط‌گیر Android ‏(AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"گزینه‌های ورودی"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"فرمان‌های گزارش‌گیری پژوهش"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"غلط‌گیر املای Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"جستجوی نام مخاطبین"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"غلط‌گیر املا از ورودی‌های لیست مخاطبین شما استفاده می‌کند"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"لرزش با فشار کلید"</string>
@@ -132,11 +134,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ورودی صدا غیرفعال است"</string>
     <string name="configure_input_method" msgid="373356270290742459">"پیکربندی روش‌های ورودی"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"زبان‌های ورودی"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"ارسال بازخورد"</string>
     <string name="select_language" msgid="3693815588777926848">"زبان‌های ورودی"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"برای ذخیره دوباره لمس کنید"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"دیکشنری موجود است"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"فعال کردن بازخورد کاربر"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"با ارسال خودکار آمارهای کاربرد و گزارش‌های خرابی به Google، به بهبود این ویرایشگر روش ورودی کمک کنید."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"طرح زمینه صفحه‌کلید"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"انگلیسی (بریتانیا)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"انگلیسی (امریکا)"</string>
@@ -163,9 +167,12 @@
     <string name="not_now" msgid="6172462888202790482">"اکنون خیر"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"سبک ورودی مشابهی در حال حاضر وجود دارد: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"حالت بررسی قابلیت استفاده"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"تنظیمات تأخیر فشار طولانی کلید"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"تنظیمات مدت زمان لرزش فشار کلید"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"تنظیمات میزان صدای فشار کلید"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"خواندن فایل فرهنگ لغت خارجی"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"فایل فرهنگ لغتی در پوشه دانلودها وجود ندارد"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"یک فایل فرهنگ لغت برای نصب انتخاب کنید"</string>
@@ -174,39 +181,34 @@
     <string name="button_default" msgid="3988017840431881491">"پیش‌فرض"</string>
     <string name="language_settings" msgid="1671153053201809031">"زبان و ورودی"</string>
     <string name="select_input_method" msgid="4301602374609275003">"انتخاب روش ورودی"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"ارائه‌دهنده فرهنگ لغت"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"ارائه دهنده فرهنگ لغت"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"سرویس فرهنگ لغت"</string>
-    <string name="download_description" msgid="3274861514695032954">"اطلاعات به‌روزرسانی فرهنگ لغت"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"فرهنگ‌های لغت افزودنی"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"فرهنگ لغت در دسترس"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"تنظیمات برای فرهنگ‌ لغت‌ها"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"فرهنگ‌های لغت کاربر"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"فرهنگ‌ لغت کاربر"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"فرهنگ لغت موجود است"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"موارد در حال دانلود کنونی"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"نصب شد"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"نصب شد، غیرفعال شد"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"مشکل اتصال به سرویس فرهنگ لغت"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"هیچ فرهنگ لغتی موجود نیست"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"بازخوانی"</string>
-    <string name="last_update" msgid="3101549719827600346">"تاریخ آخرین به‌روزرسانی"</string>
-    <string name="message_updating" msgid="820186276704134720">"درحال بررسی به‌روزرسانی‌ها"</string>
-    <string name="message_loading" msgid="8611339149825047446">"در حال بارگیری..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"فرهنگ‌ لغت اصلی"</string>
-    <string name="cancel" msgid="5586531736609183304">"لغو"</string>
-    <string name="install_dict" msgid="5525005524697607865">"نصب"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"لغو دانلود"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"غیرفعال کردن"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"فعال کردن"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"حذف"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"یک فرهنگ لغت برای <xliff:g id="LANGUAGE">%1$s</xliff:g> در دسترس است"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"برای مرور و دانلود فشار دهید"</string>
+    <string name="app_name" msgid="6320102637491234792">"ارائه‌دهنده فرهنگ لغت"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"ارائه‌دهنده فرهنگ لغت"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"سرویس فرهنگ لغت"</string>
+    <string name="download_description" msgid="6014835283119198591">"اطلاعات به‌روزرسانی فرهنگ لغت"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"فرهنگ‌ لغت‌های افزودنی"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"فرهنگ لغت موجود است"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"تنظیمات برای فرهنگ‌ لغت‌ها"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"فرهنگ‌های لغت کاربر"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"فرهنگ‌ لغت کاربر"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"فرهنگ لغت موجود است"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"موارد در حال دانلود فعلی"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"نصب شده"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"نصب شد، غیرفعال شد"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"مشکل اتصال به سرویس فرهنگ لغت"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"هیچ فرهنگ لغتی موجود نیست"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"بازخوانی"</string>
+    <string name="last_update" msgid="730467549913588780">"آخرین به‌روزرسانی"</string>
+    <string name="message_updating" msgid="4457761393932375219">"در حال بررسی به‌روزرسانی‌ها"</string>
+    <string name="message_loading" msgid="8689096636874758814">"در حال بارگیری…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"فرهنگ‌ لغت اصلی"</string>
+    <string name="cancel" msgid="6830980399865683324">"لغو"</string>
+    <string name="install_dict" msgid="180852772562189365">"نصب"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"لغو"</string>
+    <string name="delete_dict" msgid="756853268088330054">"حذف"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"برای زبان انتخاب شده در دستگاه همراه شما فرهنگ لغتی موجود است.&lt;br/&gt; توصیه می‌کنیم فرهنگ لغت <xliff:g id="LANGUAGE">%1$s</xliff:g> را &lt;b&gt;دانلود کنید&lt;/b&gt; تا بهتر تایپ کنید.&lt;br/&gt; &lt;br/&gt; دانلود از طریق 3G ممکن است چند لحظه طول بکشد. اگر &lt;b&gt;طرح داده نامحدود&lt;/b&gt; نداشته باشید ممکن است برایتان هزینه داشته باشد.&lt;br/&gt; اگر مطمئن نیستید طرح داده شما چیست٬ توصیه می‌کنیم یک اتصال Wi-Fi پیدا کنید تا دانلود بطور خودکار شروع شود.&lt;br/&gt; &lt;br/&gt; نکته: می‌توانید فرهنگ لغت را با رفتن به منوی &lt;b&gt;زبان و ورودی&lt;/b&gt; در &lt;b&gt;تنظیمات&lt;/b&gt; در دستگاه همراه خود دانلود و حذف کنید."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"هم‌اکنون بارگیری شود (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> مگابایت)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"دانلود ازطریق Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"یک فرهنگ لغت برای <xliff:g id="LANGUAGE">%1$s</xliff:g> موجود است"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"برای مرور و دانلود فشار دهید"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"دانلود لغات پیشنهادی برای <xliff:g id="LANGUAGE">%1$s</xliff:g> به زودی شروع می‌شود."</string>
 </resources>
diff --git a/java/res/values-fi/strings-appname.xml b/java/res/values-fi/strings-appname.xml
deleted file mode 100644
index b2e23d5..0000000
--- a/java/res/values-fi/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android-näppäimistö"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android-oikoluku"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android-näppäimistön asetukset"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Oikolukuasetukset"</string>
-</resources>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 624e4e6..c537d32 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-näppäimistö (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-näppäimistö (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-näppäimistön asetukset (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-oikoluku (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android-oikoluvun asetukset (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Syöttövalinnat"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Tutkimuslokin komennot"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-oikoluku (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Hae kontaktien nimiä"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Oikeinkirjoituksen tarkistus käyttää kontaktiluettelosi tietoja."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Käytä värinää näppäimiä painettaessa"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Ääniohjaus on pois käytöstä"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Määritä syöttötavat"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Syöttökielet"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Lähetä palautetta"</string>
     <string name="select_language" msgid="3693815588777926848">"Syöttökielet"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tallenna koskettamalla uudelleen"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sanakirja saatavilla"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Ota käyttäjäpalaute käyttöön"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Auta parantamaan tätä syöttötavan muokkausohjelmaa lähettämällä automaattisesti käyttötietoja ja kaatumisraportteja Googlelle."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Näppäimistöteema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"englanti (Iso-Britannia)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"englanti (Yhdysvallat)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ei nyt"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sama tulotyyli on jo olemassa: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Käytettävyystutkimustila"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Näppäimen pitkän painalluksen viiveasetukset"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Näppäimenpainalluksen värinän kestoasetukset"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Näppäimenpainalluksen äänenvoimakkuusasetukset"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lue ulkoista sanakirjatiedostoa"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Lataukset-kansiossa ei ole sanakirjatiedostoja"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Valitse asennettava sanakirjatiedosto"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Oletusarvot"</string>
     <string name="language_settings" msgid="1671153053201809031">"Kieli ja syöttötapa"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Valitse syöttötapa"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Sanakirjan tarjoaja"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Sanakirjan tarjoaja"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Sanakirjapalvelu"</string>
-    <string name="download_description" msgid="3274861514695032954">"Sanakirjan päivitystiedot"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Sanakirjalisäosat"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Sanakirja saatavilla"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Sanakirjojen asetukset"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Käyttäjän sanakirjat"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Käyttäjän sanakirja"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Sanakirja saatavilla"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Ladataan parhaillaan"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Asennettu"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Asennettu, poistettu käytöstä"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Ongelma yhd. sanak.palveluun"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Ei sanakirj. saatav."</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Päivitä"</string>
-    <string name="last_update" msgid="3101549719827600346">"Viimeksi päivitetty"</string>
-    <string name="message_updating" msgid="820186276704134720">"Tarkistetaan päivityksiä"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Ladataan..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Pääsanakirja"</string>
-    <string name="cancel" msgid="5586531736609183304">"Peruuta"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Asenna"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Peruuta lataus"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Poista käytöstä"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Ota käyttöön"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Poista"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Kielen <xliff:g id="LANGUAGE">%1$s</xliff:g> sanakirja on saatavilla"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Paina tätä, jos haluat tarkastella kohdetta tai ladata sen"</string>
+    <string name="app_name" msgid="6320102637491234792">"Sanakirjan tarjoaja"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Sanakirjan tarjoaja"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Sanakirjapalvelu"</string>
+    <string name="download_description" msgid="6014835283119198591">"Sanakirjan päivitystiedot"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Sanakirjalisäosat"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Sanakirja saatavilla"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Sanakirjojen asetukset"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Käyttäjän sanakirjat"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Käyttäjän sanakirja"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Sanakirja saatavilla"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Ladataan parhaillaan"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Asennettu"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Asennettu, poistettu käytöstä"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Ongelma yhdistettässä sanakirjapalveluun"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Ei sanakirjoja saatavilla"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Päivitä"</string>
+    <string name="last_update" msgid="730467549913588780">"Päivitetty viimeksi"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Tarkistetaan päivityksiä"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Ladataan…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Pääsanakirja"</string>
+    <string name="cancel" msgid="6830980399865683324">"Peruuta"</string>
+    <string name="install_dict" msgid="180852772562189365">"Asenna"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Peruuta"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Poista"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Laitteesi käyttökielelle on saatavilla sanakirja.&lt;br/&gt; Suosittelemme <xliff:g id="LANGUAGE">%1$s</xliff:g>-sanakirjan &lt;b&gt;lataamista&lt;/b&gt;, sillä se helpottaa laitteella kirjoittamista.&lt;br/&gt; &lt;br/&gt; Lataus kestää useimmiten muutaman minuutin 3G-yhteydellä. Latauksesta saatetaan periä maksu, ellei käytössäsi ole &lt;b&gt;rajoittamatonta tiedonsiirtopakettia&lt;/b&gt;.&lt;br/&gt; Jos et ole varma tiedonsiirtosopimuksesi tyypistä, etsi käyttöösi wifi-yhteys, niin lataus alkaa automaattisesti.&lt;br/&gt; &lt;br/&gt; Vinkki: voit ladata ja poistaa sanakirjoja mobiililaitteesi &lt;b&gt;Asetukset&lt;/b&gt;-valikon &lt;b&gt;Kieli ja syöttötapa&lt;/b&gt; -osiossa."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Lataa nyt (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> Mt)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Lataa wifi-yhteydellä"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Kielen <xliff:g id="LANGUAGE">%1$s</xliff:g> sanakirja on saatavilla"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Paina tätä, jos haluat tarkastella kohdetta tai ladata sen"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Ladataan: pian ehdotuksia näytetään kielellä <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-fr/strings-appname.xml b/java/res/values-fr/strings-appname.xml
deleted file mode 100644
index 8e2a6e0..0000000
--- a/java/res/values-fr/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Clavier Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Correcteur orthographique Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Paramètres du clavier Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Paramètres du correcteur orthographique"</string>
-</resources>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 7788e5c..c5771a1 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Clavier Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Clavier Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Paramètres du clavier Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Correcteur orthographique Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Paramètres du correcteur orthographique Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Commandes journaux rech."</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Correcteur orthographique Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Rechercher noms contacts"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Correcteur orthographique utilise entrées de liste de contacts."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Saisie vocale désactivée"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string>
     <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Autoriser les commentaires des utilisateurs"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Contribuer à l\'amélioration de cet éditeur du mode de saisie grâce à l\'envoi automatique de statistiques d\'utilisation et de rapports d\'incident à Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (Royaume-Uni)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (États-Unis)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Pas maintenant"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Le style de saisie suivant existe déjà : <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'étude de l\'utilisabilité"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Paramètres de temporisation lors d\'un appui prolongé sur une touche"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Durée de vibration à chaque pression"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volume sonore à chaque pression"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lire un fichier de dictionnaire externe"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Aucun fichier de dictionnaire dans le dossier \"Téléchargements\""</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Sélectionner un fichier de dictionnaire à installer"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Par défaut"</string>
     <string name="language_settings" msgid="1671153053201809031">"Langue et saisie"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Sélectionnez le mode de saisie"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Fournisseur de dictionnaires"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Fournisseur de dictionnaires"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Service de dictionnaires"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informations relatives à la mise à jour des dictionnaires"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Dictionnaires complémentaires"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dictionnaire disponible"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Paramètres des dictionnaires"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Dictionnaires personnels"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Dictionnaire personnel"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Dictionnaire disponible"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"En cours de téléchargement…"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installé"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installé, désactivé"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Pas de service dictionnaire."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Aucun dictionnaire."</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Actualiser"</string>
-    <string name="last_update" msgid="3101549719827600346">"Dernière mise à jour"</string>
-    <string name="message_updating" msgid="820186276704134720">"Recherche de mises à jour en cours…"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Chargement…"</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Dictionnaire principal"</string>
-    <string name="cancel" msgid="5586531736609183304">"Annuler"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installer"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Annuler le téléchargement"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Désactiver"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Activer"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Supprimer"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Un dictionnaire est disponible pour la langue sélectionnée sur votre appareil mobile.&lt;br/&gt; Nous vous invitons à &lt;b&gt;télécharger&lt;/b&gt; le dictionnaire <xliff:g id="LANGUAGE">%1$s</xliff:g> pour faciliter votre saisie.&lt;br/&gt; &lt;br/&gt; Le téléchargement peut prendre une à deux minutes via une connexion 3G. Des frais peuvent s\'appliquer si vous ne disposez pas d\'un &lt;b&gt;forfait Internet illimité&lt;/b&gt;.&lt;br/&gt; Si vous n\'êtes pas sûr de votre forfait, nous vous conseillons d\'utiliser une connexion Wi-Fi pour lancer automatiquement le téléchargement.&lt;br/&gt; &lt;br/&gt; Astuce : Vous pouvez télécharger et supprimer des dictionnaires dans &lt;b&gt;Langue et saisie&lt;/b&gt; du menu &lt;b&gt;Paramètres&lt;/b&gt; de votre appareil mobile."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Télécharger maintenant (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> Mo)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Télécharger via Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Un dictionnaire est disponible en <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Appuyez ici pour consulter et télécharger le dictionnaire."</string>
+    <string name="app_name" msgid="6320102637491234792">"Fournisseur de dictionnaires"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Fournisseur de dictionnaires"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Service de dictionnaires"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informations relatives à la mise à jour des dictionnaires"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Dictionnaires complémentaires"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dictionnaire disponible"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Paramètres des dictionnaires"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Dictionnaires personnels"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Dictionnaire personnel"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dictionnaire disponible"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Téléchargement en cours…"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installé"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installé, désactivé"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Pas de service dico."</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Aucun dictionnaire"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Actualiser"</string>
+    <string name="last_update" msgid="730467549913588780">"Dernière mise à jour"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Recherche de mises à jour en cours…"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Chargement en cours..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Dictionnaire principal"</string>
+    <string name="cancel" msgid="6830980399865683324">"Annuler"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installer"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Annuler"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Supprimer"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Un dictionnaire est disponible pour la langue sélectionnée sur votre appareil mobile.&lt;br/&gt; Nous vous invitons à &lt;b&gt;télécharger&lt;/b&gt; le dictionnaire <xliff:g id="LANGUAGE">%1$s</xliff:g> pour faciliter votre saisie.&lt;br/&gt; &lt;br/&gt; Le téléchargement peut prendre une à deux minutes via une connexion 3G. Des frais peuvent s\'appliquer si vous ne disposez pas d\'un &lt;b&gt;forfait Internet illimité&lt;/b&gt;.&lt;br/&gt; Si vous n\'êtes pas sûr de votre forfait, nous vous conseillons d\'utiliser une connexion Wi-Fi pour lancer automatiquement le téléchargement.&lt;br/&gt; &lt;br/&gt; Astuce : Vous pouvez télécharger et supprimer des dictionnaires dans la section &lt;b&gt;Langue et saisie&lt;/b&gt; du menu &lt;b&gt;Paramètres&lt;/b&gt; de votre appareil mobile."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Télécharger (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> Mo)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Télécharger via Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Un dictionnaire est disponible en <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Appuyez ici pour consulter et télécharger le dictionnaire."</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"En cours de téléchargement. Des suggestions pour la langue suivante seront bientôt disponibles : <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-hi/strings-appname.xml b/java/res/values-hi/strings-appname.xml
deleted file mode 100644
index 02283af..0000000
--- a/java/res/values-hi/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android कीबोर्ड"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android वर्तनी परीक्षक"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android कीबोर्ड सेटिंग"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"वर्तनी जांच सेटिंग"</string>
-</resources>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 4676034..d7f9dc7 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android कीबोर्ड (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android कीबोर्ड (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android कीबोर्ड सेटिंग (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android वर्तनी परीक्षक (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android वर्तनी परीक्षक सेटिंग (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"इनपुट विकल्‍प"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"लॉग आदेशों का शोध करें"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android वर्तनी परीक्षक (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"संपर्क नामों को खोजें"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"वर्तनी परीक्षक आपकी संपर्क सूची की प्रविष्टियों का उपयोग करता है"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"कुंजी दबाने पर कंपन करता है"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ध्‍वनि इनपुट अक्षम है"</string>
     <string name="configure_input_method" msgid="373356270290742459">"इनपुट पद्धति कॉन्‍फ़िगर करें"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"इनपुट भाषा"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"फ़ीडबैक भेजें"</string>
     <string name="select_language" msgid="3693815588777926848">"इनपुट भाषाएं"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"सहेजने के लिए पुन: स्‍पर्श करें"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"शब्‍दकोश उपलब्‍ध है"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"उपयोगकर्ता फ़ीडबैक सक्षम करें"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"उपयोग के आंकड़े और क्रैश रिपोर्ट Google को अपने आप भेज कर इस इनपुट पद्धति संपादक को बेहतर बनाने में सहायता करें."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"कीबोर्ड थीम"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"अंग्रेज़ी (यूके)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"अंग्रेज़ी (यूएस)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"अभी नहीं"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"ऐसी ही इनपुट शैली पहले से मौजूद है: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"उपयोगिता अध्ययन मोड"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"कुंजी को देर तक दबाने के विलंब की सेटिंग"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"कुंजी-स्‍पर्श कंपन अवधि सेटिंग"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"कुंजी-स्‍पर्श ध्‍वनि वॉल्‍यूम सेटिंग"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"बाहरी डिक्शनरी फ़ाइल पढ़ें"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"डाउनलोड फ़ोल्डर में कोई शब्दकोश फ़ाइल नहीं है"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"इंस्टॉल करने के लिए कोई शब्दकोश फ़ाइल चुनें"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"डिफ़ॉल्ट"</string>
     <string name="language_settings" msgid="1671153053201809031">"भाषा और इनपुट"</string>
     <string name="select_input_method" msgid="4301602374609275003">"इनपुट पद्धति चुनें"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"डिक्‍शनरी प्रदाता"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"डिक्‍शनरी प्रदाता"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"डिक्‍शनरी सेवा"</string>
-    <string name="download_description" msgid="3274861514695032954">"डिक्‍शनरी अपडेट जानकारी"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"एड-ऑन डिक्शनरी"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"डिक्‍शनरी उपलब्‍ध"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"डिक्‍शनरी के लिए सेटिंग"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"उपयोगकर्ता डिक्शनरी"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"उपयोगकर्ता डिक्शनरी"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"डिक्शनरी उपलब्‍ध"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"वर्तमान में डाउनलोड हो रहा है"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"इंस्‍टॉल है"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"इंस्‍टॉल है, अक्षम है"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"डिक्‍श. सेवा से कनेक्‍ट करने में समस्‍या"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"कोई डिक्‍शनरी उपलब्‍ध नहीं"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"रीफ़्रेश करें"</string>
-    <string name="last_update" msgid="3101549719827600346">"अंतिम अपडेट"</string>
-    <string name="message_updating" msgid="820186276704134720">"अपडेट देखे जा रहे हैं"</string>
-    <string name="message_loading" msgid="8611339149825047446">"लोड हो रही है..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"मुख्‍य डिक्‍शनरी"</string>
-    <string name="cancel" msgid="5586531736609183304">"रद्द करें"</string>
-    <string name="install_dict" msgid="5525005524697607865">"इंस्‍टॉल करें"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"डाउनलोड रद्द करें"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"अक्षम करें"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"सक्षम करें"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"हटाएं"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"<xliff:g id="LANGUAGE">%1$s</xliff:g> के लिए डिक्‍शनरी उपलब्‍ध है"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"समीक्षा और डाउनलोड करने के लिए दबाएं"</string>
+    <string name="app_name" msgid="6320102637491234792">"डिक्‍शनरी प्रदाता"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"डिक्‍शनरी प्रदाता"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"डिक्‍शनरी सेवा"</string>
+    <string name="download_description" msgid="6014835283119198591">"डिक्‍शनरी अपडेट जानकारी"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"एड-ऑन डिक्शनरी"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"डिक्शनरी उपलब्‍ध"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"डिक्‍शनरी की सेटिंग"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"उपयोगकर्ता डिक्शनरी"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"उपयोगकर्ता डिक्शनरी"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"डिक्शनरी उपलब्‍ध"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"वर्तमान में डाउनलोड हो रही है"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"इंस्‍टॉल है"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"इंस्‍टॉल है, अक्षम है"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"डिक्शनरी सेवा से कनेक्ट करने में समस्या"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"डिक्‍शनरी अनुपलब्‍ध"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"रीफ़्रेश करें"</string>
+    <string name="last_update" msgid="730467549913588780">"अंतिम अपडेट"</string>
+    <string name="message_updating" msgid="4457761393932375219">"अपडेट देखे जा रहे हैं"</string>
+    <string name="message_loading" msgid="8689096636874758814">"लोड हो रही है..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"मुख्‍य डिक्‍शनरी"</string>
+    <string name="cancel" msgid="6830980399865683324">"रद्द करें"</string>
+    <string name="install_dict" msgid="180852772562189365">"इंस्टॉल करें"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"रद्द करें"</string>
+    <string name="delete_dict" msgid="756853268088330054">"हटाएं"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"आपके मोबाइल उपकरण पर चयनित भाषा में डिक्‍शनरी उपलब्‍ध है.&lt;br/&gt; आपके लेखन अनुभव को बेहतर बनाने के लिए हम <xliff:g id="LANGUAGE">%1$s</xliff:g> डिक्‍शनरी को &lt;b&gt;डाउनलोड करने&lt;/b&gt; की अनुशंसा करते हैं.&lt;br/&gt; &lt;br/&gt; 3G पर डाउनलोड होने में एक या दो मिनट लग सकते हैं. यदि आपके पास &lt;b&gt;असीमित डेटा प्लान&lt;/b&gt; नहीं है, तो शुल्‍क लग सकते हैं.&lt;br/&gt; यदि आप अपने डेटा प्लान के बारे में सुनिश्चित नहीं हैं, तो हम अपने आप डाउनलोड प्रारंभ करने के लिए Wi-Fi कनेक्‍शन ढूंढने की अनुशंसा करते हैं.&lt;br/&gt; &lt;br/&gt; युक्ति: आप अपने मोबाइल उपकरण पर &lt;b&gt;सेटिंग&lt;/b&gt; मेनू में &lt;b&gt;भाषा और इनपुट&lt;/b&gt; पर जाकर डिक्‍शनरी डाउनलोड कर सकते हैं और निकाल सकते हैं."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"अभी डाउनलोड करें (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi से डाउनलोड करें"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g> के लिए डिक्‍शनरी उपलब्‍ध है"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"समीक्षा करने और डाउनलोड करने के लिए दबाएं"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"डाउनलोड हो रहा है: <xliff:g id="LANGUAGE">%1$s</xliff:g> के लिए सुझाव जल्दी ही तैयार हो जाएंगे."</string>
 </resources>
diff --git a/java/res/values-hr/strings-appname.xml b/java/res/values-hr/strings-appname.xml
deleted file mode 100644
index 69fa2e9..0000000
--- a/java/res/values-hr/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Androidova tipkovnica"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Androidova provjera pravopisa"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Postavke Androidove tipkovnice"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Postavke provjere pravopisa"</string>
-</resources>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 1845356..6a7139e 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tipkovnica (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androidova tipkovnica (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Postavke Androidove tipkovnice (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidova provjera pravopisa (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Postavke Androidove provjere pravopisa (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opcije ulaza"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Istraživanje naredbi dnevnika"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidova provjera pravopisa (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Potražite imena kontakata"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Provjera pravopisa upotrebljava unose iz vašeg popisa kontakata"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibracija pri pritisku na tipku"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. unos onemog."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguriraj načine ulaza"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Jezici unosa"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Slanje povratnih informacija"</string>
     <string name="select_language" msgid="3693815588777926848">"Jezici unosa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dodirnite ponovo za spremanje"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Rječnik je dostupan"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Omogući korisničke povratne informacije"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Pomozite u poboljšanju ovog urednika ulazne metode automatskim slanjem statistike upotrebe i padova Googleu."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engleski (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engleski (SAD)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ne sada"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Već postoji isti stil unosa: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način studije upotrebljivosti"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Postavke odgode dugog pritiska na tipke"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Postavke trajanja vibracije kod pritiska tipke"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Postavke glasnoće zvuka kod pritiska tipke"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Čitanje datoteke vanjskog rječnika"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"U mapi Preuzimanja nema datoteka rječnika"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Odabir datoteke rječnika za instaliranje"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Zadano"</string>
     <string name="language_settings" msgid="1671153053201809031">"Jezik i unos"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Odabir načina unosa"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Davatelj rječnika"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Davatelj rječnika"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Usluga rječnika"</string>
-    <string name="download_description" msgid="3274861514695032954">"Ažurirane informacije rječnika"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Rječnici - dodaci"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dostupan je rječnik"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Postavke za rječnike"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Korisnički rječnici"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Korisnički rječnik"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Rječnik je dostupan"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Trenutačno u preuzimanju"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instalirano"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instalirano, onemogućeno"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Nema usluge rječnika"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Rječnici nedostupni"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Osvježi"</string>
-    <string name="last_update" msgid="3101549719827600346">"Zadnje ažuriranje"</string>
-    <string name="message_updating" msgid="820186276704134720">"Provjera ažuriranja"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Učitavanje..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Glavni rječnik"</string>
-    <string name="cancel" msgid="5586531736609183304">"Odustani"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instaliraj"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Otkaži preuzimanje"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Onemogući"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Omogući"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Izbriši"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Dostupan je rječnik za <xliff:g id="LANGUAGE">%1$s</xliff:g> jezik"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Pritisnite za pregled i preuzimanje"</string>
+    <string name="app_name" msgid="6320102637491234792">"Davatelj rječnika"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Davatelj rječnika"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Usluga rječnika"</string>
+    <string name="download_description" msgid="6014835283119198591">"Ažurirane informacije rječnika"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Rječnici dodaci"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dostupan je rječnik"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Postavke za rječnike"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Korisnički rječnici"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Korisnički rječnik"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dostupan je rječnik"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Trenutačno se preuzima"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instalirano"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instalirano, onemogućeno"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Nema usluge rječnika"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Rječnici nedostupni"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Osvježavanje"</string>
+    <string name="last_update" msgid="730467549913588780">"Zadnje ažuriranje"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Provjera ažuriranja"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Učitavanje..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Glavni rječnik"</string>
+    <string name="cancel" msgid="6830980399865683324">"Odustani"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instaliraj"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Odustani"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Izbriši"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Dostupan je rječnik za odabrani jezik na vašem uređaju.&lt;br/&gt; Preporučujemo &lt;b&gt;preuzimanje&lt;/b&gt; rječnika za <xliff:g id="LANGUAGE">%1$s</xliff:g> radi boljeg doživljaja unosa teksta.&lt;br/&gt; &lt;br/&gt; Na 3G mreži preuzimanje može potrajati minutu ili dvije. Može podlijegati naplati ako nemate &lt;b&gt;neograničenu podatkovnu tarifu&lt;/b&gt;.&lt;br/&gt; Ako niste sigurni koju tarifu imate, preporučujemo da pronađete Wi-Fi mrežu i pokrenete automatsko preuzimanje.&lt;br/&gt; &lt;br/&gt; Savjet: rječnike možete preuzeti i ukloniti u odjeljku &lt;b&gt;Jezik i unos&lt;/b&gt; na izborniku &lt;b&gt;Postavke&lt;/b&gt; na mobilnom uređaju."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Preuzmi sada (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Preuzmi putem Wi-Fi mreže"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Dostupan je rječnik za <xliff:g id="LANGUAGE">%1$s</xliff:g> jezik"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Pritisnite za pregled i preuzimanje"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Preuzimanje: prijedlozi za <xliff:g id="LANGUAGE">%1$s</xliff:g> bit će spremni uskoro."</string>
 </resources>
diff --git a/java/res/values-hu/strings-appname.xml b/java/res/values-hu/strings-appname.xml
deleted file mode 100644
index ad511cf..0000000
--- a/java/res/values-hu/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android-billentyűzet"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Androidos helyesírás-ellenőrző"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android-billentyűzet beállításai"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"A helyesírás-ellenőrzés beállításai"</string>
-</resources>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 55cd3c2..1dd9a03 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-billentyűzet (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-billentyűzet (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-billentyűzet beállításai (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidos helyesírás-ellenőrző (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Androidos helyesírás-ellenőrző beállításai (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Beviteli beállítások"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Naplózási parancsok"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidos helyesírás-ellenőrző (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Névjegyek keresése"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"A helyesírás-ellenőrző használja a névjegyek bejegyzéseit"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés billentyű megnyomása esetén"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hangbevivel KI"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Beviteli módok beállítása"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Beviteli nyelvek"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Visszajelzés küldése"</string>
     <string name="select_language" msgid="3693815588777926848">"Beviteli nyelvek"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Érintse meg újból a mentéshez"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Van elérhető szótár"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Felhasználói visszajelzés engedélyezése"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Segíthet ennek a beviteli módszernek a javításában, ha engedélyezi a használati statisztikák és a hibajelentések elküldését a Google-nak."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Billentyűzettéma"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angol (brit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angol (amerikai)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Most nem"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ugyanez a bemenetstílus már létezik: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Használhatósági teszt"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Gomb hosszú megnyomásának késleltetési beállítása"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Gombnyomás rezgési időtartamának beállításai"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Gombnyomás hangerejének beállításai"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Külső szótárfájl olvasása"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nincs szótárfájl a Letöltések mappában."</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Válasszon ki egy szótárfájlt a telepítéshez."</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Alapértelmezett"</string>
     <string name="language_settings" msgid="1671153053201809031">"Nyelv és bevitel"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Beviteli mód kiválasztása"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Szótárszolgáltató"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Szótárszolgáltató"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Szótár szolgáltatás"</string>
-    <string name="download_description" msgid="3274861514695032954">"Szótárfrissítéssel kapcsolatos információk"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Bővítmények: szótárak"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Van rendelkezésre álló szótár"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Szótárak beállításai"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Felhasználói szótárak"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Felhasználói szótár"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Van rendelkezésre álló szótár"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Jelenlegi letöltések"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Telepítve"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Telepítve, kikapcsolva"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Csatlakozási hiba"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Nincs szótár"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Frissítés"</string>
-    <string name="last_update" msgid="3101549719827600346">"Utoljára frissítve"</string>
-    <string name="message_updating" msgid="820186276704134720">"Frissítések keresése"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Betöltés..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Fő szótár"</string>
-    <string name="cancel" msgid="5586531736609183304">"Mégse"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Telepítés"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Letöltés megszakítása"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Kikapcsolás"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Bekapcsolás"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Törlés"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"<xliff:g id="LANGUAGE">%1$s</xliff:g> nyelvhez van rendelkezésre álló szótár"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Nyomja meg az áttekintéshez és letöltéshez"</string>
+    <string name="app_name" msgid="6320102637491234792">"Szótárszolgáltató"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Szótárszolgáltató"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Szótárszolgáltatás"</string>
+    <string name="download_description" msgid="6014835283119198591">"Szótárfrissítéssel kapcsolatos információk"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Bővítmények: szótárak"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Van rendelkezésre álló szótár"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Szótárak beállításai"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Felhasználói szótárak"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Felhasználói szótár"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Van rendelkezésre álló szótár"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Jelenlegi letöltések"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Telepítve"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Telepítve, kikapcsolva"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Csatlakozási hiba"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Nincs szótár"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Frissítés"</string>
+    <string name="last_update" msgid="730467549913588780">"Legutóbb frissítve"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Frissítések keresése"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Betöltés..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Fő szótár"</string>
+    <string name="cancel" msgid="6830980399865683324">"Mégse"</string>
+    <string name="install_dict" msgid="180852772562189365">"Telepítés"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Mégse"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Törlés"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"A mobileszközön kiválasztott nyelvhez szótár érhető el.&lt;br/&gt; A gépelési élmény javításához javasoljuk a(z) <xliff:g id="LANGUAGE">%1$s</xliff:g> szótár &lt;b&gt;letöltését.&lt;br/&gt; &lt;br/&gt; A letöltés 3G hálózaton keresztül néhány percig tart. Ha &lt;b&gt;előfizetése nem korlátlan&lt;/b&gt;, a letöltés költségekkel járhat.&lt;br/&gt; Ha nem biztos abban, hogy milyen adatcsomagot használ, javasoljuk, hogy keressen egy Wi-Fi kapcsolatot a letöltés automatikus elindításához.&lt;br/&gt; &lt;br/&gt; Tipp: a szótárakat a mobileszköz &lt;b&gt;Beállítások&lt;/b&gt; menüjében a &lt;b&gt;Nyelv és bevitel&lt;/b&gt; részben töltheti le és távolíthatja el."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Töltse le most (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Letöltés Wi-Fivel"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g> nyelvhez van rendelkezésre álló szótár"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Nyomja meg az áttekintéshez és letöltéshez"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Letöltés: a(z) <xliff:g id="LANGUAGE">%1$s</xliff:g> nyelvvel kapcsolatos javaslatok hamarosan elérhetők lesznek."</string>
 </resources>
diff --git a/java/res/values-in/strings-appname.xml b/java/res/values-in/strings-appname.xml
deleted file mode 100644
index 283d692..0000000
--- a/java/res/values-in/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Keyboard Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Pemeriksa ejaan Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Setelan keyboard Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Setelan pemeriksa ejaan"</string>
-</resources>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index f9b028c..cd9b817 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Keyboard Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Keyboard Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Setelan Keyboard Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Pemeriksa Ejaan Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Setelan Pemeriksa Ejaan Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opsi masukan"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Riset Perintah Log"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pemeriksa ejaan Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kontak"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pemeriksa ejaan menggunakan entri dari daftar kontak Anda"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar jika tombol ditekan"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Masukan suara dinonaktifkan"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan metode masukan"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Bahasa masukan"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Kirim masukan"</string>
     <string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus yang tersedia"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Aktifkan masukan pengguna"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Bantu tingkatkan metode editor masukan dengan mengirim statistik penggunaan dan laporan kerusakan ke Google secara otomatis."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema keyboard"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inggris (Inggris)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inggris (AS)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Nanti saja"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sudah ada gaya masukan yang sama: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode studi daya guna"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Setelan penundaan tekan lama tombol"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Setelan durasi getaran saat tombol ditekan"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Setelan volume suara saat tombol ditekan"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Membaca file kamus eksternal"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Tidak ada file kamus di folder Unduhan"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pilih file kamus untuk dipasang"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Default"</string>
     <string name="language_settings" msgid="1671153053201809031">"Bahasa &amp; masukan"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Pilih metode masukan"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Penyedia Kamus"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Penyedia Kamus"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Layanan Kamus"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informasi pembaruan kamus"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Kamus pengaya"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Kamus tersedia"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Setelan untuk kamus"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Kamus pengguna"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Kamus pengguna"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Kamus yang tersedia"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Saat ini sedang mengunduh"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Terpasang"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Terpasang, dinonaktifkan"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Masalah koneksi ke layanan kamus"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Tidak tersedia kamus"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Segarkan"</string>
-    <string name="last_update" msgid="3101549719827600346">"Terakhir diperbarui"</string>
-    <string name="message_updating" msgid="820186276704134720">"Memeriksa pembaruan"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Memuat..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Kamus utama"</string>
-    <string name="cancel" msgid="5586531736609183304">"Batal"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Pasang"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Batalkan unduhan"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Nonaktifkan"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Aktifkan"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Hapus"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Kamus tersedia untuk bahasa <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Tekan untuk meninjau dan mengunduh"</string>
+    <string name="app_name" msgid="6320102637491234792">"Penyedia Kamus"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Penyedia Kamus"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Layanan Kamus"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informasi pembaruan kamus"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Kamus add-on"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Kamus yang tersedia"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Setelan untuk kamus"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Kamus pengguna"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Kamus pengguna"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Kamus yang tersedia"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Saat ini sedang mengunduh"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Terpasang"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Terpasang, dinonaktifkan"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Problem koneksi kamus"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Tidak tersedia kamus"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Segarkan"</string>
+    <string name="last_update" msgid="730467549913588780">"Terakhir diperbarui"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Memeriksa pembaruan"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Memuat..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Kamus utama"</string>
+    <string name="cancel" msgid="6830980399865683324">"Batal"</string>
+    <string name="install_dict" msgid="180852772562189365">"Pasang"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Batal"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Hapus"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Bahasa pilihan pada perangkat seluler Anda memiliki kamus yang tersedia.&lt;br/&gt; Silakan &lt;b&gt;mengunduh&lt;/b&gt; kamus <xliff:g id="LANGUAGE">%1$s</xliff:g> untuk meningkatkan pengalaman pengetikan.&lt;br/&gt; &lt;br/&gt; Unduhan dapat berlangsung selama satu atau dua menit melalui 3G. Mungkin dikenakan tagihan data jika Anda tidak memiliki &lt;b&gt;paket data tak terbatas&lt;/b&gt;.&lt;br/&gt; Jika tidak yakin paket data mana yang Anda miliki, sebaiknya Anda mencari sambungan Wi-Fi untuk memulai unduhan secara otomatis.&lt;br/&gt; &lt;br/&gt; Kiat: Anda dapat mengunduh atau menghapus kamus dengan membuka &lt;b&gt;Bahasa &amp; masukan&lt;/b&gt; di menu &lt;b&gt;Setelan&lt;/b&gt; perangkat seluler Anda."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Unduh sekarang (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Unduh melalui Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Kamus tersedia untuk bahasa <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Tekan untuk meninjau dan mengunduh"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Mengunduh: saran untuk bahasa <xliff:g id="LANGUAGE">%1$s</xliff:g> akan segera tersedia."</string>
 </resources>
diff --git a/java/res/values-it/strings-appname.xml b/java/res/values-it/strings-appname.xml
deleted file mode 100644
index b84896b..0000000
--- a/java/res/values-it/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Tastiera Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Controllo ortografico Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Impostazioni tastiera Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Impostazioni di controllo ortografico"</string>
-</resources>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 52a99c4..028a7a2 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastiera Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Tastiera Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Impostazioni tastiera Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Controllo ortografico Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Impostazioni controllo ortografico Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opzioni inserimento"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Ricerca comandi di log"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Controllo ortografico Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca in nomi contatti"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"La funzione di controllo ortografico usa voci dell\'elenco contatti"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrazione tasti"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input vocale disatt."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configura metodi di immissione"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Lingue comandi"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Invia feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Lingue comandi"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tocca di nuovo per salvare"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Attiva commenti degli utenti"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Aiuta a migliorare l\'editor del metodo di inserimento inviando automaticamente a Google statistiche sull\'utilizzo e segnalazioni sugli arresti anomali."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema della tastiera"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglese (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglese (USA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Non ora"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Esiste già uno stile di inuput uguale: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modalità Studio sull\'usabilità"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Impostazioni di ritardo per pressione lunga sui tasti"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Durata vibrazione alla pressione tasto"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volume audio alla pressione di un tasto"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Leggi file dizionario esterno"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nessun file di dizionario nella cartella Download"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Seleziona un file di dizionario da installare"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Predefinito"</string>
     <string name="language_settings" msgid="1671153053201809031">"Lingua e input"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Scegli il metodo di immissione"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Dictionary Provider"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Dictionary Provider"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Servizio dizionario"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informazioni aggiornate dizionari"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Dizionari aggiuntivi"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dizionario disponibile"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Impostazioni per dizionari"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Dizionari utente"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Dizionario utente"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Dizionario disponibile"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"In fase di download"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installato"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installato, disabilitato"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problema conness. dizion."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Nessun dizionario"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Aggiorna"</string>
-    <string name="last_update" msgid="3101549719827600346">"Ultimo aggiornamento"</string>
-    <string name="message_updating" msgid="820186276704134720">"Verifica disponibilità aggiornamenti"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Caricamento..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Dizionario principale"</string>
-    <string name="cancel" msgid="5586531736609183304">"Annulla"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installa"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Annulla download"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Disattiva"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Abilita"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Elimina"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"La lingua selezionata sul tuo dispositivo mobile ha un dizionario disponibile.&lt;br/&gt; Ti consigliamo di &lt;b&gt;scaricare&lt;/b&gt; il dizionario di <xliff:g id="LANGUAGE">%1$s</xliff:g> per migliorare l\'esperienza di digitazione.&lt;br/&gt; &lt;br/&gt; Il download potrebbe richiedere un paio di minuti su reti 3G. Potrebbero essere applicate delle tariffe se non disponi di un &lt;b&gt;piano dati illimitato&lt;/b&gt;.&lt;br/&gt; Se non sai bene quale piano dati è in uso, ti consigliamo di trovare una connessione Wi-Fi per avviare il download automaticamente.&lt;br/&gt; &lt;br/&gt; Suggerimento. Puoi scaricare e rimuovere i dizionari passando a &lt;b&gt;Lingue e immissione&lt;/b&gt; nel menu &lt;b&gt;Impostazioni&lt;/b&gt; del tuo dispositivo mobile."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Scarica ora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Scarica tramite Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"È disponibile un dizionario per <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Premi per esaminare e scaricare"</string>
+    <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Servizio dizionario"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informazioni aggiornamento dizionari"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Dizionari aggiuntivi"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dizionario disponibile"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Impostazioni per dizionari"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Dizionari utente"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Dizionario utente"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dizionario disponibile"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"In fase di download"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installato"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installato, disabilitato"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Conness. diz. imposs"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Nessun dizionario"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Aggiorna"</string>
+    <string name="last_update" msgid="730467549913588780">"Ultimo aggiornamento"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Verifica disponibilità aggiornamenti"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Caricamento in corso..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Dizionario principale"</string>
+    <string name="cancel" msgid="6830980399865683324">"Annulla"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installa"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Annulla"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Elimina"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Per la lingua selezionata sul dispositivo mobile è disponibile un dizionario.&lt;br/&gt; Ti consigliamo di &lt;b&gt;scaricare&lt;/b&gt; il dizionario in <xliff:g id="LANGUAGE">%1$s</xliff:g> per migliorare l\'esperienza di digitazione.&lt;br/&gt; &lt;br/&gt; Il download potrebbe richiedere un paio di minuti su 3G. Potrebbero essere applicati costi se non disponi di un &lt;b&gt;piano dati illimitato&lt;/b&gt;.&lt;br/&gt; Se non sei sicuro di quale sia il tuo piano dati, dovresti trovare una connessione Wi-Fi per avviare il download automaticamente.&lt;br/&gt; &lt;br/&gt; Suggerimento. Puoi scaricare e rimuovere dizionari passando a &lt;b&gt;Lingue e immissione&lt;/b&gt; nel menu &lt;b&gt;Impostazioni&lt;/b&gt; del dispositivo mobile."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Scarica ora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Scarica tramite Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"È disponibile un dizionario per <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Premi per esaminare e scaricare"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Download: i suggerimenti per <xliff:g id="LANGUAGE">%1$s</xliff:g> saranno pronti a breve."</string>
 </resources>
diff --git a/java/res/values-iw/strings-appname.xml b/java/res/values-iw/strings-appname.xml
deleted file mode 100644
index f3f4b67..0000000
--- a/java/res/values-iw/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"מקלדת Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"בודק האיות של Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"הגדרות מקלדת Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"הגדרות בדיקת איות"</string>
-</resources>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 9e5411b..fa6ccd5 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"מקלדת Android ‏(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"מקלדת Android‏ (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"הגדרות מקלדת Android‏ (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"בודק האיות של Android‏ (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"הגדרות בודק האיות של Android‏ (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"אפשרויות קלט"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"פקודות יומן מחקר"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"בודק האיות של Android ‏(AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"חפש שמות של אנשי קשר"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"בודק האיות משתמש בערכים מרשימת אנשי הקשר שלך"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"רטט בלחיצה על מקשים"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"הקלט הקולי מושבת"</string>
     <string name="configure_input_method" msgid="373356270290742459">"הגדרת שיטות קלט"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"שפות קלט"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"שלח משוב"</string>
     <string name="select_language" msgid="3693815588777926848">"שפות קלט"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"גע שוב כדי לשמור"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"מילון זמין"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"הפוך משוב ממשתמשים לפעיל"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"עזור לשפר את עורך שיטת הקלט על ידי שליחה אוטומטית של סטטיסטיקת שימוש ודוחות קריסת מחשב ל-Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"עיצוב מקלדת"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"אנגלית (בריטניה)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"אנגלית (ארה\"ב)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"לא עכשיו"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"סגנון קלט זהה כבר קיים: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"מצב מחקר שימושיות"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"הגדרות השהייה בעת לחיצה ארוכה על מקש"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"הגדרות משך רטט בלחיצה על מקש"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"הגדרות עוצמת קול בלחיצה על מקש"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"קריאה של קובץ מילון חיצוני"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"אין קובצי מילונים בתיקיית ההורדות"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"בחירת קובץ מילון להתקנה"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"ברירת מחדל"</string>
     <string name="language_settings" msgid="1671153053201809031">"שפה וקלט"</string>
     <string name="select_input_method" msgid="4301602374609275003">"בחירת שיטת קלט"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"ספק המילון"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"ספק המילון"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"שירות מילון"</string>
-    <string name="download_description" msgid="3274861514695032954">"פרטי עדכון מילון"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"הוספת מילונים"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"מילון זמין"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"הגדרות עבור מילונים"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"מילוני משתמש"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"מילון משתמש"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"מילון זמין"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"מוריד כעת"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"מותקן"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"מותקן, מושבת"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"בעיה בהתחברות לשירות המילון"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"אין מילונים זמינים"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"רענן"</string>
-    <string name="last_update" msgid="3101549719827600346">"עודכן לאחרונה"</string>
-    <string name="message_updating" msgid="820186276704134720">"מחפש עדכונים"</string>
-    <string name="message_loading" msgid="8611339149825047446">"טוען..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"מילון ראשי"</string>
-    <string name="cancel" msgid="5586531736609183304">"ביטול"</string>
-    <string name="install_dict" msgid="5525005524697607865">"התקן"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"בטל הורדה"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"השבת"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"הפוך לפעיל"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"מחק"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"לשפה הנבחרת במכשיר הנייד שלך יש מילון זמין.&lt;br/&gt; אנו ממליצים &lt;b&gt;להוריד&lt;/b&gt; את המילון ב<xliff:g id="LANGUAGE">%1$s</xliff:g> כדי לשפר את חוויית ההקלדה.&lt;br/&gt; &lt;br/&gt; ההורדה עשויה לארוך דקה או שתיים ב-3G. ייתכן שתחויב אם אין לך &lt;b&gt;תוכנית נתונים בלתי מוגבלת&lt;/b&gt;.&lt;br/&gt; אם אינך בטוח איזו תוכנית נתונים יש לך, אנו ממליצים לחפש חיבור Wi-Fi כדי להתחיל בהורדה באופן אוטומטי.&lt;br/&gt; &lt;br/&gt; טיפ: ניתן להוריד ולהסיר מילונים ב&lt;b&gt;שפה וקלט&lt;/b&gt; בתפריט &lt;b&gt;הגדרות&lt;/b&gt; של המכשיר הנייד שלך."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"הורד עכשיו (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"הורד באמצעות Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"יש מילון זמין עבור <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"לחץ כדי לעיין ולהוריד"</string>
+    <string name="app_name" msgid="6320102637491234792">"ספק המילון"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"ספק המילון"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"שירות מילון"</string>
+    <string name="download_description" msgid="6014835283119198591">"פרטי עדכון מילון"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"תוספי מילונים"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"מילון זמין"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"הגדרות עבור מילונים"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"מילוני משתמש"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"מילון משתמש"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"מילון זמין"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"מוריד כעת"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"מותקן"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"מותקן, מושבת"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"בעיה בהתחברות לשירות המילון"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"אין מילונים זמינים"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"רענן"</string>
+    <string name="last_update" msgid="730467549913588780">"עודכן לאחרונה"</string>
+    <string name="message_updating" msgid="4457761393932375219">"מחפש עדכונים"</string>
+    <string name="message_loading" msgid="8689096636874758814">"טוען..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"מילון ראשי"</string>
+    <string name="cancel" msgid="6830980399865683324">"ביטול"</string>
+    <string name="install_dict" msgid="180852772562189365">"התקן"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"בטל"</string>
+    <string name="delete_dict" msgid="756853268088330054">"מחק"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"לשפה הנבחרת במכשיר הנייד שלך יש מילון זמין.&lt;br/&gt; אנו ממליצים &lt;b&gt;להוריד&lt;/b&gt; את המילון ב<xliff:g id="LANGUAGE">%1$s</xliff:g> כדי לשפר את חוויית ההקלדה.&lt;br/&gt; &lt;br/&gt; ההורדה עשויה לארוך דקה או שתיים ב-3G. ייתכן שתחויב אם אין לך &lt;b&gt;תוכנית נתונים בלתי מוגבלת&lt;/b&gt;.&lt;br/&gt; אם אינך בטוח איזו תוכנית נתונים יש לך, אנו ממליצים לחפש חיבור Wi-Fi כדי להתחיל בהורדה באופן אוטומטי.&lt;br/&gt; &lt;br/&gt; טיפ: ניתן להוריד ולהסיר מילונים ב&lt;b&gt;שפה וקלט&lt;/b&gt; בתפריט &lt;b&gt;הגדרות&lt;/b&gt; של המכשיר הנייד שלך."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"הורד עכשיו (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"הורד באמצעות Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"יש מילון זמין עבור <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"לחץ כדי לעיין ולהוריד"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"מוריד: הצעות ב<xliff:g id="LANGUAGE">%1$s</xliff:g> יהיו מוכנות בקרוב."</string>
 </resources>
diff --git a/java/res/values-ja/strings-appname.xml b/java/res/values-ja/strings-appname.xml
deleted file mode 100644
index 16c1c05..0000000
--- a/java/res/values-ja/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Androidキーボード"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Androidスペルチェッカー"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Androidキーボードの設定"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"スペルチェックの設定"</string>
-</resources>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 5464d60..3c618ba 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androidキーボード(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androidキーボード(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Androidキーボードの設定(AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidスペルチェッカー(AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Androidスペルチェッカーの設定(AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"入力オプション"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"ログコマンドの検索"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidスペルチェッカー(AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"連絡先名の検索"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"スペルチェッカーでは連絡先リストのエントリを使用します"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"キー操作バイブ"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"音声入力は無効です"</string>
     <string name="configure_input_method" msgid="373356270290742459">"入力方法を設定"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"入力言語"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"フィードバックを送信"</string>
     <string name="select_language" msgid="3693815588777926848">"入力言語"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"保存するにはもう一度タップ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"辞書を利用できます"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"ユーザーフィードバックを有効にする"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"IMEの機能向上のため、使用統計状況やクラッシュレポートをGoogleに自動送信します。"</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"キーボードのテーマ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英語 (英国)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英語 (米国)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"後で行う"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"同じ入力スタイルが既に存在します: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"使いやすさの研究モード"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"キーの長押し時間の設定"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"キー操作バイブの振動時間の設定"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"キー操作音の音量設定"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"外部辞書ファイルの読み取り"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"ダウンロードフォルダに辞書ファイルはありません"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"インストールする辞書ファイルの選択"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"デフォルト"</string>
     <string name="language_settings" msgid="1671153053201809031">"言語と入力"</string>
     <string name="select_input_method" msgid="4301602374609275003">"入力方法の選択"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"辞書提供元"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"辞書提供元"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"辞書"</string>
-    <string name="download_description" msgid="3274861514695032954">"辞書のアップデート情報"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"アドオン辞書"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"辞書を利用できます"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"辞書の設定"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"単語リスト"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"単語リスト"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"辞書を利用できます"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"ダウンロードしています"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"インストール済み"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"インストール済み、無効"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"辞書に接続できません"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"辞書はありません"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"更新"</string>
-    <string name="last_update" msgid="3101549719827600346">"最終更新日"</string>
-    <string name="message_updating" msgid="820186276704134720">"アップデートを確認しています"</string>
-    <string name="message_loading" msgid="8611339149825047446">"読み込み中..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"メイン辞書"</string>
-    <string name="cancel" msgid="5586531736609183304">"キャンセル"</string>
-    <string name="install_dict" msgid="5525005524697607865">"インストール"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"ダウンロードをキャンセル"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"無効にする"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"有効にする"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"削除"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"<xliff:g id="LANGUAGE">%1$s</xliff:g>の辞書を利用できます"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"押すと確認/ダウンロードできます"</string>
+    <string name="app_name" msgid="6320102637491234792">"辞書提供元"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"辞書提供元"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"辞書"</string>
+    <string name="download_description" msgid="6014835283119198591">"辞書のアップデート情報"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"アドオン辞書"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"辞書を利用できます"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"辞書の設定"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"単語リスト"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"単語リスト"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"辞書を利用できます"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"ダウンロード中"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"インストール済み"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"インストール済み、無効"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"辞書に接続できません"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"辞書はありません"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"更新"</string>
+    <string name="last_update" msgid="730467549913588780">"最終更新"</string>
+    <string name="message_updating" msgid="4457761393932375219">"アップデートを確認しています"</string>
+    <string name="message_loading" msgid="8689096636874758814">"読み込んでいます..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"メイン辞書"</string>
+    <string name="cancel" msgid="6830980399865683324">"キャンセル"</string>
+    <string name="install_dict" msgid="180852772562189365">"インストール"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"キャンセル"</string>
+    <string name="delete_dict" msgid="756853268088330054">"削除"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"お使いの携帯端末で選択した言語に対応する辞書があります。&lt;br/&gt;入力機能をより快適にご利用いただくため、<xliff:g id="LANGUAGE">%1$s</xliff:g>の辞書の&lt;b&gt;ダウンロード&lt;/b&gt;をおすすめします。&lt;br/&gt; &lt;br/&gt;3G経由の場合、ダウンロードに要する時間は1~2分です。&lt;b&gt;定額制のデータプラン&lt;/b&gt;をご利用でない場合は通信料が発生する可能性があります。&lt;br/&gt;ご利用のデータプランが不明な場合は、自動的にダウンロードが開始されるWi-Fi接続を探すことをおすすめします。&lt;br/&gt; &lt;br/&gt;ヒント: 辞書のダウンロードや削除は、お使いの携帯端末の[&lt;b&gt;設定&lt;/b&gt;]メニューの[&lt;b&gt;言語と入力&lt;/b&gt;]で行えます。"</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"今すぐダウンロード(<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi経由でダウンロード"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g>の辞書を利用できます"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"押すと確認/ダウンロードできます"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"ダウンロード中: <xliff:g id="LANGUAGE">%1$s</xliff:g>の入力候補をまもなく利用できます。"</string>
 </resources>
diff --git a/java/res/values-ko/strings-appname.xml b/java/res/values-ko/strings-appname.xml
deleted file mode 100644
index 3d7db61..0000000
--- a/java/res/values-ko/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android 키보드"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android 맞춤법 검사기"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android 키보드 설정"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"맞춤법 검사 설정"</string>
-</resources>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index ca1c2ea..14cb49a 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 키보드(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android 키보드(AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android 키보드 설정(AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android 맞춤법 검사기(AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android 맞춤법 검사기 설정(AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"입력 옵션"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"로그 명령 탐색"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 맞춤법 검사기(AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"연락처 이름 조회"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"맞춤법 검사기가 주소록의 항목을 사용합니다."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"키를 누를 때 진동 발생"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"음성 입력이 사용 중지됨"</string>
     <string name="configure_input_method" msgid="373356270290742459">"입력 방법 설정"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"입력 언어"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"의견 보내기"</string>
     <string name="select_language" msgid="3693815588777926848">"입력 언어"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"저장하려면 다시 터치"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"사전 사용 가능"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"사용자 의견 사용"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"사용 통계 및 충돌 보고서를 Google에 자동으로 전송하여 입력 방법 편집기의 개선에 도움을 줍니다."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"키보드 테마"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"영어(영국)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"영어(미국)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"나중에"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"같은 입력 스타일이 다음과 같이 이미 존재합니다. <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"가용성 연구 모드"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"키 길게 누르기 지연 설정"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"키를 누를 때 진동 시간 설정"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"키를 누를 때 효과음 설정"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"외부 사전 파일 읽기"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"다운로드 폴더에 사전 파일이 없음"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"설치할 사전 파일 선택"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"기본값"</string>
     <string name="language_settings" msgid="1671153053201809031">"언어 및 키보드"</string>
     <string name="select_input_method" msgid="4301602374609275003">"입력 방법 선택"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"사전 제공업체"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"사전 제공업체"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"사전 서비스"</string>
-    <string name="download_description" msgid="3274861514695032954">"사전 업데이트 정보"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"사전 추가"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"사전 사용 가능"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"사전 설정"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"사용자 사전"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"사용자 사전"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"사전 사용 가능"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"현재 다운로드 중"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"설치됨"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"설치 완료되었으나 사용 중지됨"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"사전 서비스에 연결하는 동안 문제가 발생했습니다."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"사용할 수 있는 사전이 없습니다."</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"새로고침"</string>
-    <string name="last_update" msgid="3101549719827600346">"최근 업데이트"</string>
-    <string name="message_updating" msgid="820186276704134720">"업데이트를 확인하는 중"</string>
-    <string name="message_loading" msgid="8611339149825047446">"로드 중..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"기본 사전"</string>
-    <string name="cancel" msgid="5586531736609183304">"취소"</string>
-    <string name="install_dict" msgid="5525005524697607865">"설치"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"다운로드 취소"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"사용 중지"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"사용"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"삭제"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"<xliff:g id="LANGUAGE">%1$s</xliff:g> 사전을 사용할 수 있습니다."</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"검토하고 다운로드하려면 누르세요."</string>
+    <string name="app_name" msgid="6320102637491234792">"사전 제공업체"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"사전 제공업체"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"사전 서비스"</string>
+    <string name="download_description" msgid="6014835283119198591">"사전 업데이트 정보"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"사전 추가"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"사전 사용 가능"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"사전 설정"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"사용자 사전"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"사용자 사전"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"사전 사용 가능"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"현재 다운로드 중"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"설치됨"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"설치 완료되었으나 사용 중지됨"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"사전 서비스에 연결하는 중에 문제가 발생했습니다."</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"사용할 수 있는 사전이 없습니다."</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"새로고침"</string>
+    <string name="last_update" msgid="730467549913588780">"최종 업데이트"</string>
+    <string name="message_updating" msgid="4457761393932375219">"업데이트를 확인하는 중"</string>
+    <string name="message_loading" msgid="8689096636874758814">"로드 중..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"기본 사전"</string>
+    <string name="cancel" msgid="6830980399865683324">"취소"</string>
+    <string name="install_dict" msgid="180852772562189365">"설치"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"취소"</string>
+    <string name="delete_dict" msgid="756853268088330054">"삭제"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"기기에서 선택한 언어로 사용할 수 있는 사전이 있습니다.&lt;br/&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> 사전을 &lt;b&gt;다운로드&lt;/b&gt;하여 입력 환경을 개선해 보세요..&lt;br/&gt; &lt;br/&gt; 3G로 다운로드하는 경우 1-2분 정도 걸립니다. &lt;b&gt;무제한 데이터 요금제&lt;/b&gt;가 아닌 경우 요금이 청구됩니다.&lt;br/&gt; 사용 중인 데이터 요금제를 잘 모르는 경우 Wi-Fi에 연결할 수 있는 곳을 찾아 자동 다운로드를 시작하는 것이 좋습니다.&lt;br/&gt; &lt;br/&gt; 도움말: 사전을 다운로드하거나 삭제하려면 &lt;b&gt;언어 및 키보드&lt;/b&gt;로 이동하면 되며 이는 휴대기기의 &lt;b&gt;설정&lt;/b&gt; 메뉴에 있습니다."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"지금 다운로드(<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi를 통해 다운로드"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g> 사전을 사용할 수 있습니다."</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"검토하고 다운로드하려면 누르세요."</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"다운로드 중: <xliff:g id="LANGUAGE">%1$s</xliff:g>에 대한 추천항목이 곧 준비됩니다."</string>
 </resources>
diff --git a/java/res/values-lt/strings-appname.xml b/java/res/values-lt/strings-appname.xml
deleted file mode 100644
index 668d275..0000000
--- a/java/res/values-lt/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"„Android“ klaviatūra"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"„Android“ rašybos tikrinimo programa"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"„Android“ klaviatūros nustatymai"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Rašybos tikrinimo nustatymai"</string>
-</resources>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 49d9aec..7b51b21 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"„Android“ klaviatūra (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"„Android“ klaviatūra (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"„Android“ klaviatūros nustatymai (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"„Android“ rašybos tikrinimo programa (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"„Android“ rašybos tikrinimo programos nustatymai (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Įvesties parinktys"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Tyrinėti žurnalo komandas"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"„Android“ rašybos tikrinimo programa (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktų vardų paieška"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rašybos tikrinimo progr. naudoja įrašus, esančius kontaktų sąraše"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibruoti, kai paspaudžiami klavišai"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balso įv. neleidž."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigūruoti įvesties metodus"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Įvesties kalbos"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Siųsti atsiliepimą"</string>
     <string name="select_language" msgid="3693815588777926848">"Įvesties kalbos"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Jei norite išsaugoti, palieskite dar kartą"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Žodynas galimas"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Įgalinti naudotojų atsiliepimus"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Padėkite patobulinti šią įvesties metodo redagavimo programą automatiškai „Google“ siųsdami naudojimo statistiką ir strigčių ataskaitas."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatūros tema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglų k. (JK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglų k. (JAV)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ne dabar"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Toks pat įvesties stilius jau yra: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tinkamumo tyrimo režimas"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Klavišo ilgo paspaudimo delsos nustatymai"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Vibracijos paspaudus mygtuką trukmės nustatymai"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Garso paspaudus mygtuką garsumo nustatymai"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Skaityti išorinį žodyno failą"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Atsisiuntimų aplanke nėra žodyno failų"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pasirinkite diegiamą žodyno failą"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Numatytieji"</string>
     <string name="language_settings" msgid="1671153053201809031">"Kalba ir įvestis"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Pasirinkite įvesties metodą"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Žodyno teikėjas"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Žodyno teikėjas"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Žodyno paslauga"</string>
-    <string name="download_description" msgid="3274861514695032954">"Žodyno atnaujinimo informacija"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Papildomi žodynai"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Žodynas galimas"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Žodynų nustatymai"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Naudotojo žodynai"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Naudotojo žodynas"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Žodynas galimas"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Šiuo metu atsisiunčiama"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Įdiegta"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Įdiegta, neleidžiama"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Prisijungimo prie žodyno paslaugos problema"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Nėra galimų žodynų"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Atnaujinti"</string>
-    <string name="last_update" msgid="3101549719827600346">"Paskutinį kartą atnaujinta"</string>
-    <string name="message_updating" msgid="820186276704134720">"Ieškoma naujinių"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Įkeliama..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Pagrindinis žodynas"</string>
-    <string name="cancel" msgid="5586531736609183304">"Atšaukti"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Įdiegti"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Atšaukti atsisiuntimą"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Neleisti"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Įgalinti"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Ištrinti"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Galimas <xliff:g id="LANGUAGE">%1$s</xliff:g> žodynas"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Paspauskite, kad peržiūrėtumėte ir atsisiųstumėte"</string>
+    <string name="app_name" msgid="6320102637491234792">"Žodyno teikėjas"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Žodyno teikėjas"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Žodyno paslauga"</string>
+    <string name="download_description" msgid="6014835283119198591">"Žodyno atnaujinimo informacija"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Papildomi žodynai"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Galimas žodynas"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Žodynų nustatymai"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Naudotojo žodynai"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Naudotojo žodynas"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Galimas žodynas"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Šiuo metu atsisiunčiama"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Įdiegta"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Įdiegta, neleidžiama"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Prisijung. problema"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Nėra galimų žodynų"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Atnaujinti"</string>
+    <string name="last_update" msgid="730467549913588780">"Paskutinį kartą atnaujinta"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Ieškoma naujinių"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Įkeliama..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Pagrindinis žodynas"</string>
+    <string name="cancel" msgid="6830980399865683324">"Atšaukti"</string>
+    <string name="install_dict" msgid="180852772562189365">"Įdiegti"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Atšaukti"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Ištrinti"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Galimas mobiliajame įrenginyje pasirinktos kalbos žodynas.&lt;br/&gt; Rekomenduojame &lt;b&gt;atsisiųsti&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> žodyną, kad būtų patogiau įvesti tekstą.&lt;br/&gt; &lt;br/&gt; Atsisiuntimas per 3G turėtų trukti 1–2 min. Jei neturite &lt;b&gt;neribotų duomenų plano&lt;/b&gt;, galite būti apmokestinti.&lt;br/&gt; Jei nežinote, kokį planą turite, rekomenduojame rasti „Wi-Fi“ ryšį, kad atsisiuntimas prasidėtų automatiškai.&lt;br/&gt; &lt;br/&gt; Patarimas: galite atsisiųsti ir pašalinti žodynus mobiliojo įrenginio meniu &lt;b&gt;Nustatymai&lt;/b&gt; skiltyje &lt;b&gt;Kalba ir įvestis&lt;/b&gt;."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Atsisiųsti dabar (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Atsisiųsti per „Wi-Fi“"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Galimas <xliff:g id="LANGUAGE">%1$s</xliff:g> žodynas"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Paspauskite, kad peržiūrėtumėte ir atsisiųstumėte"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Atsisiunčiama. Netrukus bus galimi <xliff:g id="LANGUAGE">%1$s</xliff:g> pasiūlymai."</string>
 </resources>
diff --git a/java/res/values-lv/strings-appname.xml b/java/res/values-lv/strings-appname.xml
deleted file mode 100644
index e5657a2..0000000
--- a/java/res/values-lv/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android tastatūra"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android pareizrakstības pārbaudītājs"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android tastatūras iestatījumi"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Pareizrakstības pārbaudes iestatījumi"</string>
-</resources>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 4d6fb3c..676b7c4 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tastatūra (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android tastatūra (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android tastatūras iestatījumi (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android pareizrakstības pārbaudītājs (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android pareizrakstības pārbaudītāja iestatījumi (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Ievades opcijas"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Izpētes žurnāla komandas"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android pareizrakstības pārbaudītājs (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Meklēt kontaktp. vārdus"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pareizrakst. pārbaudītājs lieto ierakstus no kontaktp. saraksta."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrēt, nospiežot taustiņu"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balss iev. atspējota"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Ievades metožu konfigurēšana"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Ievades valodas"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Sūtīt atsauksmes"</string>
     <string name="select_language" msgid="3693815588777926848">"Ievades valodas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pieskarieties vēlreiz, lai saglabātu."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ir pieejama vārdnīca."</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Iespējot lietotāju atsauksmes"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Palīdziet uzlabot šo ievades metodes redaktoru, automātiski nosūtot lietojuma statistiku un pārskatus par avārijām uzņēmumam Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastatūras motīvs"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Angļu valoda (Lielbritānija)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Angļu valoda (ASV)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Vēlāk"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Šāds ievades stils jau pastāv: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Lietojamības izpētes režīms"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Taustiņa ilgās nospiešanas noildzes iestatījumi"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Taustiņu nospiešanas vibrācijas ilguma iestatījumi"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Taustiņu nospiešanas skaņas skaļuma iestatījumi"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ārējās vārdnīcas faila nolasīšana"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Mapē Lejupielādes nav neviena vārdnīcas faila."</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Instalējamā vārdnīcas faila atlasīšana"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Noklusējums"</string>
     <string name="language_settings" msgid="1671153053201809031">"Valoda un ievade"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Ievades metodes izvēle"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Vārdnīcas nodrošinātājs"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Vārdnīcas nodrošinātājs"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Vārdnīcas pakalpojums"</string>
-    <string name="download_description" msgid="3274861514695032954">"Vārdnīcas atjauninājuma informācija"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Pievienojumvārdnīcas"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Vārdnīca ir pieejama"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Vārdnīcu iestatījumi"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Lietotāja vārdnīcas"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Lietotāja vārdnīca"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Vārdnīca ir pieejama."</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Notiek lejupielāde."</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instalēta"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instalēta, atspējota"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problēma, savien. ar vārdn. pak."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Vārdn. nav pieejamas"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Atsvaidzināt"</string>
-    <string name="last_update" msgid="3101549719827600346">"Pēdējo reizi atjaunināts"</string>
-    <string name="message_updating" msgid="820186276704134720">"Notiek pārbaude, vai ir pieejami atjauninājumi."</string>
-    <string name="message_loading" msgid="8611339149825047446">"Notiek ielāde..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Galvenā vārdnīca"</string>
-    <string name="cancel" msgid="5586531736609183304">"Atcelt"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instalēt"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Atcelt lejupielādi"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Atspējot"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Iespējot"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Dzēst"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Mobilajā ierīcē atlasītajai valodai ir pieejama vārdnīca.&lt;br/&gt; Ieteicams &lt;b&gt;lejupielādēt&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> vārdnīcu, lai uzlabotu rakstīšanas iespējas.&lt;br/&gt; &lt;br/&gt; Lejupielāde, izmantojot 3G, aizņems dažas minūtes. Ja nelietojat &lt;b&gt;neierobežotu datu plānu&lt;/b&gt;, var tikt piemērota maksa.&lt;br/&gt; Ja nezināt, kādu datu plānu lietojat, atrodiet Wi-Fi savienojumu, lai automātiski sāktu lejupielādi.&lt;br/&gt; &lt;br/&gt; Padoms: vārdnīcas var lejupielādēt un noņemt mobilās ierīces izvēlnes &lt;b&gt;Iestatījumi&lt;/b&gt; sadaļā &lt;b&gt;Valodas ievade&lt;/b&gt;."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Lejupielādēt tūlīt (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Lejupielādēt, izmantojot Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Ir pieejama vārdnīca šādai valodai: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Nospiediet, lai pārskatītu un lejupielādētu"</string>
+    <string name="app_name" msgid="6320102637491234792">"Vārdnīcas nodrošinātājs"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Vārdnīcas nodrošinātājs"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Vārdnīcas pakalpojums"</string>
+    <string name="download_description" msgid="6014835283119198591">"Vārdnīcas atjauninājuma informācija"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Pievienojumvārdnīcas"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Vārdnīca ir pieejama"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Vārdnīcu iestatījumi"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Lietotāja vārdnīcas"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Lietotāja vārdnīca"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Vārdnīca ir pieejama"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Pašreiz tiek lejupielādēta"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instalēta"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instalēta, atspējota"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Nevar savien. ar vārdnīcas pakalp."</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Vārdn. nav pieejamas"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Atsvaidzināt"</string>
+    <string name="last_update" msgid="730467549913588780">"Pēdējo reizi atjaunināts"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Notiek pārbaude, vai ir pieejami atjauninājumi."</string>
+    <string name="message_loading" msgid="8689096636874758814">"Notiek ielāde..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Galvenā vārdnīca"</string>
+    <string name="cancel" msgid="6830980399865683324">"Atcelt"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instalēt"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Atcelt"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Dzēst"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Mobilajā ierīcē atlasītajai valodai ir pieejama vārdnīca.&lt;br/&gt;Ieteicams &lt;b&gt;lejupielādēt&lt;/b&gt; vārdnīcu (<xliff:g id="LANGUAGE">%1$s</xliff:g>), lai uzlabotu rakstīšanas iespējas.&lt;br/&gt;&lt;br/&gt;Lejupielāde, izmantojot 3G tīklu, ilgs dažas minūtes. Ja nelietojat &lt;b&gt;neierobežotu datu plānu&lt;/b&gt;, var tikt piemērota maksa.&lt;br/&gt;Ja nezināt, kādu datu plānu lietojat, ieteicams atrast Wi-Fi savienojumu, lai automātiski sāktu lejupielādi.&lt;br/&gt;&lt;br/&gt;Padoms. Vārdnīcas var lejupielādēt un noņemt mobilās ierīces izvēlnes &lt;b&gt;Iestatījumi&lt;/b&gt; sadaļā &lt;b&gt;Valoda un ievade&lt;/b&gt;."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Lejupielādēt tūlīt (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Lejupielādēt, izmantojot Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Ir pieejama vārdnīca šādai valodai: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Nospiediet, lai pārskatītu un lejupielādētu"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Notiek lejupielāde. Drīz būs pieejami ieteikumi šādai valodai: <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-ms/strings-appname.xml b/java/res/values-ms/strings-appname.xml
deleted file mode 100644
index 73b5537..0000000
--- a/java/res/values-ms/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Papan kekunci Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Penyemak ejaan Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Tetapan papan kekunci Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Tetapan penyemakan ejaan"</string>
-</resources>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index 7bcc286..96e2b8c 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Papan kekunci Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Papan kekunci Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Tetapan Papan Kekunci Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Penyemak Ejaan Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Tetapan Penyemak Ejaan Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Pilihan input"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Arahan Log Penyelidikan"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Penyemak ejaan Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Penyemak ejaan menggunakan entri dari senarai kenalan anda"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar pada tekanan kekunci"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input suara dilmphkn"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan kaedah input"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Bahasa input"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Hantar maklum balas"</string>
     <string name="select_language" msgid="3693815588777926848">"Bahasa input"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus tersedia"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Dayakan maklum balas pengguna"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Bantu memperbaik editor input ini dengan menghantar statistik penggunaan dan laporan runtuhan kepada Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema papan kekunci"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Bahasa Inggeris (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Bahasa Inggeris (AS)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Bukan sekarang"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Gaya input yang sama sudah wujud: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mod kajian kebolehgunaan"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Tetapan kelengahan tekan lama kekunci"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Tetapan tempoh getaran tekan kekunci"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Tetapan kelantangan bunyi tekanan kekunci"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Baca fail kamus luaran"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Tiada fail kamus dalam folder Muat Turun"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pilih fail kamus untuk dipasang"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Lalai"</string>
     <string name="language_settings" msgid="1671153053201809031">"Bahasa &amp; input"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Pilih kaedah input"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Pembekal Kamus"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Pembekal Kamus"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Perkhidmatan Kamus"</string>
-    <string name="download_description" msgid="3274861514695032954">"Maklumat kemas kini kamus"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Kamus tambahan"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Kamus tersedia"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Tetapan untuk kamus"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Kamus pengguna"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Kamus pengguna"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Kamus tersedia"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Sedang memuat turun"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Dipasang"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Dipasang, dilumpuhkan"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Masalah menyambung kepada perkhidmatan kamus"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Tiada kamus tersedia"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Muat semula"</string>
-    <string name="last_update" msgid="3101549719827600346">"Kali terakhir dikemas kini"</string>
-    <string name="message_updating" msgid="820186276704134720">"Menyemak kemas kini"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Memuatkan..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Kamus utama"</string>
-    <string name="cancel" msgid="5586531736609183304">"Batal"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Pasang"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Batalkan muat turun"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Lumpuhkan"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Dayakan"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Padam"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Kamus tersedia untuk <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Tekan untuk mengulas dan memuat turun"</string>
+    <string name="app_name" msgid="6320102637491234792">"Pembekal Kamus"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Pembekal Kamus"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Perkhidmatan Kamus"</string>
+    <string name="download_description" msgid="6014835283119198591">"Maklumat kemas kini kamus"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Kamus tambahan"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Kamus tersedia"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Tetapan untuk kamus"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Kamus pengguna"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Kamus pengguna"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Kamus tersedia"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Sedang memuat turun"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Dipasang"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Dipasang, dilumpuhkan"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Masalah menyambung kepada perkhidmatan kamus"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Tiada kamus tersedia"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Muatkan semula"</string>
+    <string name="last_update" msgid="730467549913588780">"Kali terakhir dikemas kini"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Menyemak kemas kini"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Memuatkan..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Kamus utama"</string>
+    <string name="cancel" msgid="6830980399865683324">"Batal"</string>
+    <string name="install_dict" msgid="180852772562189365">"Pasang"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Batal"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Padam"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Bahasa pilihan pada peranti mudah alih anda mempunyai kamus tersedia.&lt;br/&gt; Kami mengesyorkan &lt;b&gt;memuat turun&lt;/b&gt; kamus <xliff:g id="LANGUAGE">%1$s</xliff:g> untuk memperbaik pengalaman menaip anda.&lt;br/&gt; &lt;br/&gt; Muat turun boleh mengambil masa seminit atau dua melalui 3G. Caj mungkin dikenakan jika anda tidak mempunyai &lt;b&gt;pelan data tanpa had&lt;/b&gt;.&lt;br/&gt; Jika anda tidak pasti jenis pelan data yang anda miliki, kami mengesyorkan agar anda mencari sambungan Wi-Fi untuk mula memuat turun secara automatik.&lt;br/&gt; &lt;br/&gt; Petua: Anda boleh memuat turun dan mengalih keluar kamus dengan pergi ke menu &lt;b&gt;Bahasa &amp; input&lt;/b&gt; dalam &lt;b&gt;Tetapan&lt;/b&gt; peranti mudah alih anda."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Muat turun sekarang (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Muat turun melalui Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Kamus tersedia untuk <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Tekan untuk mengulas dan memuat turun"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Memuat turun: cadangan untuk <xliff:g id="LANGUAGE">%1$s</xliff:g> akan sedia tidak lama lagi."</string>
 </resources>
diff --git a/java/res/values-nb/strings-appname.xml b/java/res/values-nb/strings-appname.xml
deleted file mode 100644
index 56c1c3c..0000000
--- a/java/res/values-nb/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android-tastatur"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android-stavekontroll"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Innstillinger for Android-tastatur"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Innstillinger for stavekontroll"</string>
-</resources>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 2e1d44e..2cac5ba 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-tastatur (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Instillinger for Android-tastatur (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-stavekontroll (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Innstillinger for Android-stavekontroll (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Inndataalternativer"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Kommandoer for undersøkelseslogging"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontroll (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå opp kontaktnavn"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruker oppføringer fra kontaktlisten din"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer ved tastetrykk"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Taleinndata er deaktiv."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inndatametoder"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Inndataspråk"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Send tilbakemelding"</string>
     <string name="select_language" msgid="3693815588777926848">"Inndataspråk"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Trykk på nytt for å lagre"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Aktiver brukertilbakemelding"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Ved å sende bruksstatistikk og programstopprapporter til Google automatisk, hjelper du oss med å gjøre redigeringsfunksjonen for denne inndatametoden enda bedre."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannia)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ikke nå"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Inndatastilen finnes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Bruksstudiemodus"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Innstillinger for lange tastetrykk"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Innstillinger for vibrasjonsvarighet ved tastetrykk"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Innstillinger for lydstyrke ved tastetrykk"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Bruk en ekstern ordlistefil"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Det ligger ingen ordboksfiler i Nedlastinger-mappen"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Velg ordboksfilen du vil installere"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="language_settings" msgid="1671153053201809031">"Språk og inndata"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Velg inndatametode"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Ordlisteleverandør"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Ordlisteleverandør"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Ordboktjeneste"</string>
-    <string name="download_description" msgid="3274861514695032954">"Oppdateringsinformasjon for ordliste"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Tilleggsordlister"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Ordliste er tilgjengelig"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Innstillinger for ordlister"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Brukerordlister"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Brukerordliste"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Ordliste er tilgjengelig"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Laster ned nå"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installert"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installert, deaktivert"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Kan ikke koble til ordlistetjenesten"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Fant ingen ordliste"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Last inn på nytt"</string>
-    <string name="last_update" msgid="3101549719827600346">"Sist oppdatert"</string>
-    <string name="message_updating" msgid="820186276704134720">"Ser etter oppdateringer"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Laster inn …"</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Hovedordliste"</string>
-    <string name="cancel" msgid="5586531736609183304">"Avbryt"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installer"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Avbryt nedlastingen"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Deaktiver"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Aktiver"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Slett"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Det valgte språket på mobileneheten din har en tilgjengelig ordliste.&lt;br/&gt; Vi anbefaler å &lt;b&gt;laste ned&lt;/b&gt; ordlisten for <xliff:g id="LANGUAGE">%1$s</xliff:g>. Dette forbedrer skriveopplevelsen din.&lt;br/&gt; &lt;br/&gt; Nedlastingen kan ta fra ett til to minutter via 3G. Belastninger kan påløpe hvis du ikke har et abonnement med &lt;b&gt;ubegrenset databruk&lt;/b&gt;.&lt;br/&gt; Hvis du er usikker på hvilken abonnementstype du har, anbefaler vi deg å finne en Wi-Fi-tilkobling for å starte nedlastingen automatisk.&lt;br/&gt; &lt;br/&gt; Tips: Du kan laste ned og fjerne ordlister ved å gå til &lt;b&gt;Språk og inndata&lt;/b&gt; i menyen for &lt;b&gt;Innstillinger&lt;/b&gt; på mobilenheten din."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Last ned nå (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Last ned via Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"En ordliste er tilgjengelig for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Trykk for å se gjennom og laste ned"</string>
+    <string name="app_name" msgid="6320102637491234792">"Ordlisteleverandør"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Ordlisteleverandør"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Ordlistetjeneste"</string>
+    <string name="download_description" msgid="6014835283119198591">"Oppdateringsinformasjon for ordliste"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Tilleggsordlister"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Ordliste tilgjengelig"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Innstillinger for ordlister"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Brukerordlister"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Brukerordbok"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Ordliste tilgjengelig"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Laster ned nå"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installert"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installert, deaktivert"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Kan ikke koble til ordlistetjenesten"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Fant ingen ordlister"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Last inn på nytt"</string>
+    <string name="last_update" msgid="730467549913588780">"Sist oppdatert"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Ser etter oppdateringer ..."</string>
+    <string name="message_loading" msgid="8689096636874758814">"Laster inn …"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Hovedordliste"</string>
+    <string name="cancel" msgid="6830980399865683324">"Avbryt"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installer"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Avbryt"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Slett"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Det valgte språket på mobilenheten din har en tilgjengelig ordliste.&lt;br/&gt; Vi anbefaler å &lt;b&gt;laste ned&lt;/b&gt; ordlisten for <xliff:g id="LANGUAGE">%1$s</xliff:g>. Dette forbedrer skriveopplevelsen din.&lt;br/&gt; &lt;br/&gt; Nedlastingen kan ta fra ett til to minutter via 3G. Belastninger kan påløpe hvis du ikke har et abonnement med &lt;b&gt;ubegrenset databruk&lt;/b&gt;.&lt;br/&gt; Hvis du er usikker på hvilken abonnementstype du har, anbefaler vi deg å finne en Wi-Fi-tilkobling for å starte nedlastingen automatisk.&lt;br/&gt; &lt;br/&gt; Tips: Du kan laste ned og fjerne ordlister ved å gå til &lt;b&gt;Språk og inndata&lt;/b&gt; i menyen for &lt;b&gt;Innstillinger&lt;/b&gt; på mobilenheten din."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Last ned nå (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Last ned via Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"En ordliste er tilgjengelig for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Trykk for å se gjennom og laste ned"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Laster ned: forslag blir snart tilgjengelige for <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-nl/strings-appname.xml b/java/res/values-nl/strings-appname.xml
deleted file mode 100644
index ee288ef..0000000
--- a/java/res/values-nl/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android-toetsenbord"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Spellingcontrole van Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Instellingen voor Android-toetsenbord"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Instellingen voor spellingcontrole"</string>
-</resources>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 55aee63..93be4ea 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-toetsenbord (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-toetsenbord (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Instellingen voor het Android-toetsenbord (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Spellingcontrole van Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Instellingen voor spellingcontrole van Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropties"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Opdrachten in onderzoekslogbestand"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Spellingcontrole van Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Contactnamen opzoeken"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"De spellingcontrole gebruikt items uit uw contactenlijst"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Trillen bij toetsaanslag"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spraakinvoer is uit"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Invoermethoden configureren"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Invoertalen"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Feedback verzenden"</string>
     <string name="select_language" msgid="3693815588777926848">"Invoertalen"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak nogmaals aan om op te slaan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Gebruikersfeedback inschakelen."</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Help deze invoermethode te verbeteren door automatisch gebruiksstatistieken en crashmeldingen naar Google te verzenden."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Toetsenbordthema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engels (GB)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Niet nu"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Dezelfde invoerstijl bestaat al: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus voor gebruiksvriendelijkheidsonderzoek"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Instellingen voor vertraging bij toets ingedrukt houden"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Instellingen voor trillingsduur bij druk op een toets"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Instellingen voor geluidsvolume bij druk op een toets"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Extern woordenboekbestand lezen"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Geen woordenboekbestanden in de map \'Downloads\'"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecteer een woordenboekbestand om te installeren"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Standaard"</string>
     <string name="language_settings" msgid="1671153053201809031">"Taal en invoer"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Invoermethode selecteren"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Woordenboekleverancier"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Woordenboekleverancier"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Woordenboekservice"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informatie over woordenboekupdate"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Woordenboeken toevoegen"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Woordenboek beschikbaar"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Instellingen voor woordenboeken"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Gebruikerswoordenboeken"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Gebruikerswoordenboek"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Woordenboek beschikbaar"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Wordt gedownload"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Geïnstalleerd"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Geïnstalleerd, uitgeschakeld"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Verbindingsprobleem woordenboekservice"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Geen woordenboeken"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Vernieuwen"</string>
-    <string name="last_update" msgid="3101549719827600346">"Laatst bijgewerkt"</string>
-    <string name="message_updating" msgid="820186276704134720">"Controleren op updates"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Laden..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Algemeen woordenboek"</string>
-    <string name="cancel" msgid="5586531736609183304">"Annuleren"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installeren"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Download annuleren"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Uitschakelen"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Inschakelen"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Verwijderen"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Er is een woordenboek beschikbaar voor de geselecteerde taal op uw mobiele apparaat.&lt;br/&gt; We raden u aan het woordenboek voor het <xliff:g id="LANGUAGE">%1$s</xliff:g> te &lt;b&gt;downloaden&lt;/b&gt; om uw typevaardigheid te verbeteren.&lt;br/&gt; &lt;br/&gt; De download kan een of twee minuten duren via 3G. Er kunnen kosten worden berekend als u geen &lt;b&gt;onbeperkt gegevensabonnement&lt;/b&gt; heeft.&lt;br/&gt; Als u niet zeker weet welk gegevensabonnement u heeft, raden we u aan een wifi-verbinding te zoeken om de download automatisch te starten.&lt;br/&gt; &lt;br/&gt; Tip: u kunt woordenboeken downloaden en verwijderen door naar &lt;b&gt;Taal en invoer&lt;/b&gt; in het menu &lt;b&gt;Instellingen&lt;/b&gt; van uw mobiele apparaat te gaan."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Nu downloaden (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Downloaden via wifi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Er is een woordenboek beschikbaar voor <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Druk om te controleren en te downloaden"</string>
+    <string name="app_name" msgid="6320102637491234792">"Woordenboekleverancier"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Woordenboekleverancier"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Woordenboekservice"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informatie over woordenboekupdate"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Woordenboeken toevoegen"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Woordenboek beschikbaar"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Instellingen voor woordenboeken"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Gebruikerswoordenboeken"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Gebruikerswoordenboek"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Woordenboek beschikbaar"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Wordt gedownload"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Geïnstalleerd"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Geïnstalleerd, uitgeschakeld"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Verbindingsprobleem woordenboekservice"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Geen woordenboeken"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Vernieuwen"</string>
+    <string name="last_update" msgid="730467549913588780">"Laatst bijgewerkt"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Controleren op updates"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Wordt geladen…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Algemeen woordenboek"</string>
+    <string name="cancel" msgid="6830980399865683324">"Annuleren"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installeren"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Annuleren"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Verwijderen"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Er is een woordenboek voor de geselecteerde taal beschikbaar op uw mobiele apparaat.&lt;br/&gt; We raden u aan het woordenboek voor het <xliff:g id="LANGUAGE">%1$s</xliff:g> te &lt;b&gt;downloaden&lt;/b&gt; om uw typvaardigheid te verbeteren.&lt;br/&gt; &lt;br/&gt; De download kan één of twee minuten duren via 3G. Er kunnen kosten worden berekend als u geen &lt;b&gt;onbeperkt gegevensabonnement&lt;/b&gt; heeft.&lt;br/&gt; Als u niet zeker weet welk gegevensabonnement u heeft, raden we u aan een wifi-verbinding te zoeken om de download automatisch te starten.&lt;br/&gt; &lt;br/&gt; Tip: u kunt woordenboeken downloaden en verwijderen via &lt;b&gt;Taal en invoer&lt;/b&gt; in het menu &lt;b&gt;Instellingen&lt;/b&gt; van uw mobiele apparaat."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Nu downloaden (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Downloaden via wifi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Er is een woordenboek beschikbaar voor het <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Druk om te controleren en te downloaden"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Downloaden: suggesties voor het <xliff:g id="LANGUAGE">%1$s</xliff:g> zijn straks beschikbaar."</string>
 </resources>
diff --git a/java/res/values-pl/strings-appname.xml b/java/res/values-pl/strings-appname.xml
deleted file mode 100644
index 4d244d7..0000000
--- a/java/res/values-pl/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Klawiatura Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Sprawdzanie pisowni w Androidzie"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Ustawienia klawiatury Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Ustawienia sprawdzania pisowni"</string>
-</resources>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 68fed40..c9f98f7 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klawiatura Androida (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Klawiatura Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Ustawienia klawiatury Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Sprawdzanie pisowni na Androidzie (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Ustawienia sprawdzania pisowni na Androidzie (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Polecenia dziennika badań"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Sprawdzanie pisowni na Androidzie (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj kontakty"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Sprawdzanie pisowni bierze pod uwagę wpisy z listy kontaktów."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Wibracja przy naciśnięciu"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Rozpoznawanie mowy jest wyłączone"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguruj metody wprowadzania"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Języki wprowadzania"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Prześlij opinię"</string>
     <string name="select_language" msgid="3693815588777926848">"Języki wprowadzania"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotknij ponownie, aby zapisać"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Słownik dostępny"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Włącz przesyłanie opinii użytkownika"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Pomóż ulepszyć edytor wprowadzania tekstu, automatycznie wysyłając do Google statystyki użycia i raporty o awariach."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Motyw klawiatury"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Angielska (Wielka Brytania)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Angielska (Stany Zjednoczone)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Nie teraz"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Taki styl wprowadzania już istnieje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tryb badania przydatności"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Ustawienia opóźnienia przy przytrzymaniu przycisku"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Czas trwania wibracji przy naciśnięciu"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Głośność dźwięku przy naciśnięciu"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Odczyt zewnętrznego pliku słownika"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Brak plików słownika w folderze Pobrane pliki"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Wybierz plik słownika do zainstalowania"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Domyślne"</string>
     <string name="language_settings" msgid="1671153053201809031">"Język, klawiatura, głos"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Wybierz metodę wprowadzania"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Dostawca słownika"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Dostawca słownika"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Usługa słownika"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informacje o aktualizacji słownika"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Słowniki dodatkowe"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dostępny słownik"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Ustawienia słowników"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Słowniki użytkownika"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Słownik użytkownika"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Słownik jest dostępny"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Aktualnie pobierany"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Zainstalowany"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Zainstalowany, wyłączony"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problem z połączeniem z usługą słownika"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Brak słowników"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Odśwież"</string>
-    <string name="last_update" msgid="3101549719827600346">"Ostatnia aktualizacja"</string>
-    <string name="message_updating" msgid="820186276704134720">"Sprawdzanie dostępności aktualizacji"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Wczytywanie..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Słownik główny"</string>
-    <string name="cancel" msgid="5586531736609183304">"Anuluj"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Zainstaluj"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Anuluj pobieranie"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Wyłącz"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Włącz"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Usuń"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Dla języka: <xliff:g id="LANGUAGE">%1$s</xliff:g> jest dostępny słownik"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Naciśnij, aby sprawdzić i pobrać"</string>
+    <string name="app_name" msgid="6320102637491234792">"Dostawca słownika"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Dostawca słownika"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Usługa słownika"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informacje o aktualizacji słownika"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Słowniki dodatkowe"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Słownik dostępny"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Ustawienia słowników"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Słowniki użytkownika"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Słownik użytkownika"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Słownik dostępny"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Aktualnie pobierany"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Zainstalowany"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Zainstalowany, wyłączony"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Problem z połączeniem z usługą słownika"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Brak słowników"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Odśwież"</string>
+    <string name="last_update" msgid="730467549913588780">"Ostatnia aktualizacja"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Sprawdzanie dostępności aktualizacji"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Wczytuję..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Słownik główny"</string>
+    <string name="cancel" msgid="6830980399865683324">"Anuluj"</string>
+    <string name="install_dict" msgid="180852772562189365">"Zainstaluj"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Anuluj"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Usuń"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Dla języka, którego używasz na swoim urządzeniu przenośnym, jest dostępny słownik.&lt;br/&gt; Warto &lt;b&gt;pobrać&lt;/b&gt; ten słownik <xliff:g id="LANGUAGE">%1$s</xliff:g>, by ułatwić sobie pisanie.&lt;br/&gt; &lt;br/&gt; Pobieranie trwa do dwóch minut (przez 3G). Jeśli nie masz &lt;b&gt;abonamentu z nieograniczoną transmisją danych&lt;/b&gt;, operator może naliczyć opłatę.&lt;br/&gt; Jeśli nie wiesz, jaki masz abonament, połącz się z Wi-Fi, by automatycznie rozpocząć pobieranie.&lt;br/&gt; &lt;br/&gt; Wskazówka: słowniki możesz pobierać i usuwać na urządzeniu w sekcji &lt;b&gt;Język, klawiatura, głos&lt;/b&gt; w menu &lt;b&gt;Ustawienia&lt;/b&gt;."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Pobierz teraz (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Pobierz przez Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Dostępny jest słownik <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Naciśnij, by sprawdzić i pobrać"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Pobieranie – wkrótce będą dostępne sugestie w tym języku: <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-pt-rPT/strings-appname.xml b/java/res/values-pt-rPT/strings-appname.xml
deleted file mode 100644
index 1b88acb..0000000
--- a/java/res/values-pt-rPT/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Teclado do Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Verificador ortográfico do Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Definições de teclado do Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Definições da verificação ortográfica"</string>
-</resources>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 15ff65b..ee4c1cb 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Definições do Teclado Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Verificador Ortográfico Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Definições do Verificador Ortográfico Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opções de introdução"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos de Reg. Invest."</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificador ortográfico do Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Procurar nomes de contac."</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico utiliza entradas da sua lista de contactos"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao primir as teclas"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. voz desact."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introdução"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string>
     <string name="select_language" msgid="3693815588777926848">"Idiomas de introdução"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Activar comentários do utilizador"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Envie automaticamente estatísticas de utilização e relatórios de falhas para a Google e ajude-nos a melhorar este editor de método de introdução."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (RU)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Agora não"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Já existe o mesmo estilo de introdução: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo da capacidade de utilização"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Definições do atraso de pressão longa de tecla"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Definições de duração da vibração ao premir as teclas"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Definições de volume de som ao premir as teclas"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ler ficheiro de dicionário externo"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Não há ficheiros de dicionário na pasta Transferências"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecione um ficheiro de dicionário para instalar"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Predefinido"</string>
     <string name="language_settings" msgid="1671153053201809031">"Idioma e entrada de som"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Escolher o método de entrada"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Fornecedor de Dicionário"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Fornecedor de Dicionário"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Serviço de Dicionário"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informações de atualização do dicionário"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Dicionários suplementares"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dicionário disponível"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Definições dos dicionários"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Dicionários do utilizador"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Dicionário do utilizador"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Dicionário disponível"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Transferência em curso"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instalado"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instalado, desativado"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problema ao ligar ao serviço de dicionário"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Sem dicionários disponíveis"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Atualizar"</string>
-    <string name="last_update" msgid="3101549719827600346">"Última atualização"</string>
-    <string name="message_updating" msgid="820186276704134720">"A verificar existência de atualizações"</string>
-    <string name="message_loading" msgid="8611339149825047446">"A carregar..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Dicionário principal"</string>
-    <string name="cancel" msgid="5586531736609183304">"Cancelar"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instalar"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Cancelar transferência"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Desativar"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Ativar"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Eliminar"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"O idioma selecionado no seu dispositivo móvel tem um dicionário disponível.&lt;br/&gt; Recomendamos que &lt;b&gt;transfira&lt;/b&gt; o dicionário <xliff:g id="LANGUAGE">%1$s</xliff:g> para melhorar a sua experiência de introdução.&lt;br/&gt; &lt;br/&gt; A transferência pode demorar um ou dois minutos via 3G. Poderão ser aplicadas taxas se não tiver um &lt;b&gt;plano de dados ilimitado&lt;/b&gt;.&lt;br/&gt; Se não tiver a certeza do plano de dados que tem, recomendamos que localize uma ligação Wi-Fi para começar a transferência automaticamente.&lt;br/&gt; &lt;br/&gt; Sugestão: pode transferir e remover dicionários acedendo a &lt;b&gt;Idioma e introdução&lt;/b&gt; no menu &lt;b&gt;Definições&lt;/b&gt; do seu dispositivo móvel."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Transferir agora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Transferir via Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Está disponível um dicionário para <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Prima para consultar e transferir"</string>
+    <string name="app_name" msgid="6320102637491234792">"Fornecedor de Dicionário"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Fornecedor de Dicionário"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Serviço de Dicionário"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informações de atualização do dicionário"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Dicionários suplementares"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dicionário disponível"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Definições dos dicionários"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Dicionários do utilizador"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Dicionário do utilizador"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dicionário disponível"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Transferência em curso"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instalado"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instalado, desativado"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Problema ao ligar ao serviço de dicionário"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Nenhum dicionário"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Atualizar"</string>
+    <string name="last_update" msgid="730467549913588780">"Última atualização"</string>
+    <string name="message_updating" msgid="4457761393932375219">"A verificar existência de atualizações"</string>
+    <string name="message_loading" msgid="8689096636874758814">"A carregar..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Dicionário principal"</string>
+    <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instalar"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Cancelar"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Eliminar"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"O idioma selecionado no dispositivo móvel tem um dicionário disponível.&lt;br/&gt; Recomendamos que &lt;b&gt;transfira&lt;/b&gt; o dicionário de <xliff:g id="LANGUAGE">%1$s</xliff:g> para melhorar a sua experiência de introdução de texto.&lt;br/&gt; &lt;br/&gt; A transferência pode demorar um ou dois minutos acima de 3G. Poderão ser aplicadas taxas se não tiver um &lt;b&gt;plano de dados ilimitado&lt;/b&gt;.&lt;br/&gt; Se não tiver a certeza do plano de dados que tem, recomendamos que localize uma ligação Wi-Fi para começar a transferência automaticamente.&lt;br/&gt; &lt;br/&gt; Sugestão: pode transferir e remover dicionários acedendo a &lt;b&gt;Idioma e introdução&lt;/b&gt; no menu &lt;b&gt;Definições&lt;/b&gt; do disp. móvel."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Transferir agora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Transferir via Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Está disponível um dicionário para <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Prima para consultar e transferir"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"A transferir: as sugestões para <xliff:g id="LANGUAGE">%1$s</xliff:g> estarão prontas em breve."</string>
 </resources>
diff --git a/java/res/values-pt/strings-appname.xml b/java/res/values-pt/strings-appname.xml
deleted file mode 100644
index d78786d..0000000
--- a/java/res/values-pt/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Teclado do Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Corretor ortográfico do Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Configurações de teclado do Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Configurações de verificação ortográfica"</string>
-</resources>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 3134115..1abedd6 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Configurações de teclado Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corretor ortográfico do Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Configurações de corretor ortográfico do Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opções de entrada"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Pesq. comandos de reg."</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corretor ortográfico do Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nomes de contatos"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico usa entradas de sua lista de contatos"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao tocar a tecla"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Texto por voz desat."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string>
     <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para salvar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Ativar comentário do usuário"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Ajude a melhorar este editor de método de entrada enviando automaticamente ao Google estatísticas de uso e relatórios de falhas."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Agora não"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"O estilo de entrada já existe: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo de utilização"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Configurações de atraso ao pressionar teclas"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Configurações de duração da vibração ao tocar a tecla"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Config. volume ao tocar a tecla"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ler arquivo de dicionário externo"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nenhum arquivo de dicionário na pasta Downloads"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecione um arquivo de dicionário para instalar"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Padrão"</string>
     <string name="language_settings" msgid="1671153053201809031">"Idioma e entrada"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Selecione o método de entrada"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Provedor de dicionário"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Provedor de dicionário"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Serviço de dicionário"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informações de atualização do dicionário"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Dicionários complementares"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dicionário disponível"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Configurações dos dicionários"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Dicionário do usuário"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Dicionário do usuário"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Dicionário disponível"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Download em andamento"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instalado"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instalado, desativado"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Prob. de conexão c/ dic. de serv."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Nenhum dicionário disponível"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Atualizar"</string>
-    <string name="last_update" msgid="3101549719827600346">"Última atualização"</string>
-    <string name="message_updating" msgid="820186276704134720">"Verificando atualizações"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Carregando..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Dicionário principal"</string>
-    <string name="cancel" msgid="5586531736609183304">"Cancelar"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instalar"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Cancelar download"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Desativar"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Permitir"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Excluir"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Há um dicionário disponível para <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Pressione para consultar e fazer o download"</string>
+    <string name="app_name" msgid="6320102637491234792">"Provedor de dicionário"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Provedor de dicionário"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Serviço de dicionário"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informações de atualização do dicionário"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Dicionários complementares"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dicionário disponível"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Configurações dos dicionários"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Dicionários do usuário"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Dicionário do usuário"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dicionário disponível"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Download em andamento"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instalado"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instalado, desativado"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Prob. conexão dic."</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Nenhum dicionário disponível"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Atualizar"</string>
+    <string name="last_update" msgid="730467549913588780">"Última atualização"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Verificando atualizações"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Carregando..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Dicionário principal"</string>
+    <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instalar"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Cancelar"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Excluir"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"O idioma selecionado em seu dispositivo móvel tem um dicionário disponível.&lt;br/&gt; Recomendamos &lt;b&gt;fazer o download&lt;/b&gt; do dicionário de <xliff:g id="LANGUAGE">%1$s</xliff:g> para melhorar sua experiência de digitação.&lt;br/&gt; O download pode levar um ou dois minutos por conexão 3G. Tarifas podem ser aplicáveis caso você não tenha um &lt;b&gt;plano de dados ilimitado&lt;/b&gt;.&lt;br/&gt; Se você não tem certeza quanto a seu plano de dados, recomendamos encontrar uma conexão Wi-Fi para iniciar o download automaticamente.&lt;br/&gt; Dica: você pode fazer o download de dicionários e removê-los acessando &lt;b&gt;Idioma e entrada&lt;/b&gt; no menu &lt;b&gt;Configurações&lt;/b&gt; de seu dispositivo móvel."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Fazer o download agora (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Fazer o download por Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Há um dicionário disponível para <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Pressione para consultar e fazer o download"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Download em andamento: as sugestões para <xliff:g id="LANGUAGE">%1$s</xliff:g> estarão prontas em breve."</string>
 </resources>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index 5dad59f..15cd327 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -20,14 +20,18 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) -->
+    <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
+    <skip />
+    <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
+    <skip />
+    <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
+    <skip />
+    <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
     <skip />
     <!-- no translation found for english_ime_input_options (3909945612939668554) -->
     <skip />
     <!-- no translation found for english_ime_research_log (8492602295696577851) -->
     <skip />
-    <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
-    <skip />
     <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
     <skip />
     <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
@@ -226,13 +230,16 @@
     <!-- no translation found for configure_input_method (373356270290742459) -->
     <skip />
     <string name="language_selection_title" msgid="1651299598555326750">"Linguas da cumonds vocals"</string>
+    <!-- no translation found for send_feedback (1780431884109392046) -->
+    <skip />
     <!-- no translation found for select_language (3693815588777926848) -->
     <skip />
     <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
     <skip />
     <string name="has_dictionary" msgid="6071847973466625007">"Dicziunari disponibel"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Activar il feedback da l\'utilisader"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Gidai a meglierar quest editur da la metoda d\'endataziun cun trametter automaticamain datas statisticas davart l\'utilisaziun e rapports da collaps a Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <!-- no translation found for keyboard_layout (8451164783510487501) -->
     <skip />
     <!-- no translation found for subtype_en_GB (88170601942311355) -->
@@ -285,11 +292,11 @@
     <skip />
     <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
     <skip />
-    <!-- no translation found for prefs_key_longpress_timeout_settings (1881822418815012326) -->
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
     <skip />
-    <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
     <skip />
-    <!-- no translation found for prefs_keypress_sound_volume_settings (5875933757082305040) -->
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
     <skip />
     <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
     <skip />
@@ -307,4 +314,63 @@
     <skip />
     <!-- no translation found for select_input_method (4301602374609275003) -->
     <skip />
+    <!-- no translation found for app_name (6320102637491234792) -->
+    <skip />
+    <!-- no translation found for dictionary_provider_name (3027315045397363079) -->
+    <skip />
+    <!-- no translation found for dictionary_service_name (6237472350693511448) -->
+    <skip />
+    <!-- no translation found for download_description (6014835283119198591) -->
+    <skip />
+    <!-- no translation found for dictionary_settings_title (8091417676045693313) -->
+    <skip />
+    <!-- no translation found for dictionary_install_over_metered_network_prompt (3587517870006332980) -->
+    <skip />
+    <!-- no translation found for dictionary_settings_summary (5305694987799824349) -->
+    <skip />
+    <!-- no translation found for user_dictionaries (3582332055892252845) -->
+    <skip />
+    <!-- no translation found for default_user_dict_pref_name (1625055720489280530) -->
+    <skip />
+    <!-- no translation found for dictionary_available (4728975345815214218) -->
+    <skip />
+    <!-- no translation found for dictionary_downloading (2982650524622620983) -->
+    <skip />
+    <!-- no translation found for dictionary_installed (8081558343559342962) -->
+    <skip />
+    <!-- no translation found for dictionary_disabled (8950383219564621762) -->
+    <skip />
+    <!-- no translation found for cannot_connect_to_dict_service (9216933695765732398) -->
+    <skip />
+    <!-- no translation found for no_dictionaries_available (8039920716566132611) -->
+    <skip />
+    <!-- no translation found for check_for_updates_now (8087688440916388581) -->
+    <skip />
+    <!-- no translation found for last_update (730467549913588780) -->
+    <skip />
+    <!-- no translation found for message_updating (4457761393932375219) -->
+    <skip />
+    <!-- no translation found for message_loading (8689096636874758814) -->
+    <skip />
+    <!-- no translation found for main_dict_description (3072821352793492143) -->
+    <skip />
+    <string name="cancel" msgid="6830980399865683324">"Interrumper"</string>
+    <!-- no translation found for install_dict (180852772562189365) -->
+    <skip />
+    <!-- no translation found for cancel_download_dict (7843340278507019303) -->
+    <skip />
+    <!-- no translation found for delete_dict (756853268088330054) -->
+    <skip />
+    <!-- no translation found for should_download_over_metered_prompt (2878629598667658845) -->
+    <skip />
+    <!-- no translation found for download_over_metered (1643065851159409546) -->
+    <skip />
+    <!-- no translation found for do_not_download_over_metered (2176209579313941583) -->
+    <skip />
+    <!-- no translation found for dict_available_notification_title (6514288591959117288) -->
+    <skip />
+    <!-- no translation found for dict_available_notification_description (1075194169443163487) -->
+    <skip />
+    <!-- no translation found for toast_downloading_suggestions (1313027353588566660) -->
+    <skip />
 </resources>
diff --git a/java/res/values-ro/strings-appname.xml b/java/res/values-ro/strings-appname.xml
deleted file mode 100644
index dfa6422..0000000
--- a/java/res/values-ro/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Tastatură Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Verificator ortografic Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Setările tastaturii Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Setările de verificare ortografică"</string>
-</resources>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index d4c39af5..1e052a1 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastatură Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Tastatură Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Setări tastatură Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Verificator ortografic Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Setări verificator ortografic Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opţiuni de introducere text"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Comenzi jurnal cercetare"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificator ortografic Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Verificare nume în agendă"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Verificatorul ortografic utilizează intrări din lista de contacte"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrare la apăsarea tastei"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Intr. vocală dezact."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configuraţi metodele de intrare"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Selectaţi limba"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Trimiteți feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Limbi de intrare"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Atingeţi din nou pentru a salva"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicţionar disponibil"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Activaţi feedback de la utilizatori"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Ajutaţi la îmbunătăţirea acestui instrument de editare a metodelor de introducere a textului trimiţând în mod automat la Google statistici de utilizare şi rapoarte de blocare."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Temă pentru tastatură"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engleză (Marea Britanie)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engleză (S.U.A.)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Nu acum"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Acelaşi stil de introducere există deja: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modul Studiu privind utilizarea"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Setări pentru întârzierea la apăsarea lungă a tastei"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Setări pentru durata vibrării la apăsarea tastei"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Setări pentru volumul sunetului la apăsarea tastei"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Citiți fișierul de dicționar extern"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nu există fișiere dicționar în dosarul Descărcări"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selectați un fișier dicționar de instalat"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Prestabilit"</string>
     <string name="language_settings" msgid="1671153053201809031">"Limbă și introducere de text"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Alegeți metoda de introducere de text"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Furnizorul dicţionarului"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Furnizorul dicţionarului"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Serviciul Dicţionar"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informaţii privind actualizarea dicţionarului"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Dicţionare suplimentare"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Dicţionar disponibil"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Setări pentru dicţionare"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Dicţionarele utilizatorului"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Dicţionarul utilizatorului"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Dicţionar disponibil"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Se descarcă acum"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Instalat"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Instalat, dezactivat"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Nu se conect. dicţ."</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Niciun dicţionar"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Actualizaţi"</string>
-    <string name="last_update" msgid="3101549719827600346">"Data ultimei modificări"</string>
-    <string name="message_updating" msgid="820186276704134720">"Se verifică existenţa actualizărilor"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Se încarcă..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Dicţionar principal"</string>
-    <string name="cancel" msgid="5586531736609183304">"Anulaţi"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Instalaţi"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Anulaţi descărcarea"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Dezactivaţi"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Activaţi"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Ştergeţi"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Este disponibil un dicţionar pentru <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Apăsaţi pentru a examina şi pentru a descărca"</string>
+    <string name="app_name" msgid="6320102637491234792">"Furnizor dicționar"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Furnizor dicționar"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Serviciu dicționar"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informații privind actualizarea dicționarului"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Dicționare suplimentare"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dicționar disponibil"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Setări pentru dicționare"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Dicționarele utilizatorului"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Dicționarul utilizatorului"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dicționar disponibil"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Se descarcă acum"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Instalat"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Instalat, dezactivat"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Eroare conectare la serviciu dicționar"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Niciun dicționar"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Actualizați"</string>
+    <string name="last_update" msgid="730467549913588780">"Data ultimei modificări"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Se verifică existența actualizărilor"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Se încarcă..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Dicționar principal"</string>
+    <string name="cancel" msgid="6830980399865683324">"Anulaţi"</string>
+    <string name="install_dict" msgid="180852772562189365">"Instalați"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Anulați"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Ștergeți"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Limba selectată pe dispozitivul mobil are un dicționar disponibil.&lt;br/&gt; Vă recomandăm să &lt;b&gt;descărcați&lt;/b&gt; dicționarul de <xliff:g id="LANGUAGE">%1$s</xliff:g> pentru a vă îmbunătăți experiența la introducerea textului.&lt;br/&gt; &lt;br/&gt; Descărcarea prin 3G poate dura un minut sau două. Se pot aplica taxe dacă nu aveți un &lt;b&gt;plan de date nelimitat&lt;/b&gt;.&lt;br/&gt; Dacă nu știți sigur ce plan de date aveți, găsiți o conexiune Wi-Fi și descărcați automat.&lt;br/&gt; &lt;br/&gt; Sfat: puteți să descărcați și să eliminați dicționare accesând &lt;b&gt;Limbă și introducere de text&lt;/b&gt; din meniul &lt;b&gt;Setări&lt;/b&gt;, pe dispozitivul mobil."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Descărcați acum (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Descărcați prin Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Este disponibil un dicționar pentru <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Apăsați pentru examinare și descărcare"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Se descarcă: sugestiile pentru <xliff:g id="LANGUAGE">%1$s</xliff:g> vor fi gata în curând."</string>
 </resources>
diff --git a/java/res/values-ru/strings-appname.xml b/java/res/values-ru/strings-appname.xml
deleted file mode 100644
index 5db1d0b..0000000
--- a/java/res/values-ru/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Клавиатура Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Проверка правописания Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Настройки клавиатуры Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Настройки проверки правописания"</string>
-</resources>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 681c76d..88209b0 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавиатура Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавиатура Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Настройки клавиатуры Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Проверка правописания Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Настройки проверки правописания Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Настройки"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Все команды"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Проверка правописания Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Поиск контактов"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Обращаться к списку контактов при проверке правописания"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Виброотклик клавиш"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голосовой ввод откл."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Настройка способов ввода"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Языки ввода"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Отправить отзыв"</string>
     <string name="select_language" msgid="3693815588777926848">"Языки ввода"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Нажмите, чтобы сохранить"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Доступен словарь"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Включить отправку сведений"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Помогите усовершенствовать редактор способа ввода, разрешив отправку статистики и отчетов о сбоях в Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавиатуры"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"английский (Великобритания)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"английский (США)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Не сейчас"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Такой стиль ввода уже существует: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим проверки удобства использования"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Долгое нажатие"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки вибросигнала при нажатии клавиш"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки громкости звука при нажатии клавиш"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Считывать данные из внешнего словаря"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"В папке \"Загрузки\" нет словарей"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Выберите файл словаря"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"По умолчанию"</string>
     <string name="language_settings" msgid="1671153053201809031">"Язык и ввод"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Выберите способ ввода"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Поставщик словарей"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Поставщик словарей"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Служба словарей"</string>
-    <string name="download_description" msgid="3274861514695032954">"Обновления словаря"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Дополнительные словари"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Словарь доступен"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Настройки словарей"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Пользовательские словари"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Пользовательский словарь"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Словарь доступен"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Загрузка..."</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Установлен"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Установлен, отключен"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Ошибка подключения"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Словари недоступны"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Обновить"</string>
-    <string name="last_update" msgid="3101549719827600346">"Последнее обновление"</string>
-    <string name="message_updating" msgid="820186276704134720">"Проверка обновлений..."</string>
-    <string name="message_loading" msgid="8611339149825047446">"Загрузка..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Основной словарь"</string>
-    <string name="cancel" msgid="5586531736609183304">"Отмена"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Установить"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Отменить загрузку"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Отключить"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Включить"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Удалить"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Доступен словарь: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Нажмите, чтобы просмотреть и загрузить"</string>
+    <string name="app_name" msgid="6320102637491234792">"Поставщик словарей"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Поставщик словарей"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Служба словарей"</string>
+    <string name="download_description" msgid="6014835283119198591">"Обновления словаря"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Дополнительные словари"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Словарь доступен"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Настройки словарей"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Пользовательские словари"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Пользовательский словарь"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Доступен словарь"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Загрузка…"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Установлен"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Установлен, отключен"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Сбой подключения"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Словарей нет"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Обновить"</string>
+    <string name="last_update" msgid="730467549913588780">"Последнее обновление"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Проверка обновлений…"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Загрузка..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Основной словарь"</string>
+    <string name="cancel" msgid="6830980399865683324">"Отмена"</string>
+    <string name="install_dict" msgid="180852772562189365">"Установить"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Отмена"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Удалить"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Доступен <xliff:g id="LANGUAGE">%1$s</xliff:g> словарь для проверки правописания.&lt;br/&gt;Рекомендуем &lt;b&gt;установить&lt;/b&gt; его, чтобы быстрее вводить текст.&lt;br/&gt;&lt;br/&gt;Если вашим тарифом предусмотрена &lt;b&gt;безлимитная передача данных&lt;/b&gt;, словарь можно загрузить через сеть 3G (это займет всего пару минут).&lt;br/&gt;Если вы не помните подробностей своего тарифного плана, лучше подключитесь к сети Wi-Fi (загрузка начнется автоматически).&lt;br/&gt;&lt;br/&gt;Совет. Чтобы добавить, удалить или настроить словарь, откройте раздел &lt;b&gt;Язык и ввод&lt;/b&gt; в настройках своего устройства."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Загрузить (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> МБ)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Загрузить через Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Доступен словарь: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Нажмите, чтобы просмотреть и загрузить"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Загрузка словаря: <xliff:g id="LANGUAGE">%1$s</xliff:g>…"</string>
 </resources>
diff --git a/java/res/values-sk/strings-appname.xml b/java/res/values-sk/strings-appname.xml
deleted file mode 100644
index 5b55900..0000000
--- a/java/res/values-sk/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Klávesnica Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Kontrola pravopisu Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Nastavenia klávesnice Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Nastavenia kontroly pravopisu"</string>
-</resources>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 5d08208..7fbc1e5 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klávesnica Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Klávesnica Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Nastavenia klávesnice Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Kontrola pravopisu (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Nastavenia kontroly pravopisu Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávania textu a údajov"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Príkazy denníka výskumu"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhľadať kontakty"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používa záznamy z vášho zoznamu kontaktov"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Pri stlačení klávesu vibrovať"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup je zakázaný"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurovať metódy vstupu"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Jazyky vstupu"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Odoslať spätnú väzbu"</string>
     <string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opätovným dotykom uložíte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"K dispozícii je slovník"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Povoliť spätnú väzbu od používateľov"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Automatickým zasielaním štatistík o využívaní editora metódy vstupu a správ o jeho zlyhaní do služby Google môžete prispieť k vylepšeniu tohto nástroja."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Motív klávesnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglická klávesnica (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglická klávesnica (US)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Teraz nie"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Rovnaký štýl vstupu už existuje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim štúdie použiteľnosti"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Nastavenia oneskorenia pre stlačenie a podržanie klávesu"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Nastavenia trvania vibrovania pri stlačení klávesu"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Nastavenia hlasitosti zvuku pri stlačení klávesu"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Čítať súbor externého slovníka"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"V priečinku Preberanie nie sú žiadne súbory slovníka"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Vyberte súbor slovníka, ktorý chcete nainštalovať"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Predvolené"</string>
     <string name="language_settings" msgid="1671153053201809031">"Jazyk &amp; vstup"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Zvoliť metódu vstupu"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Poskytovateľ slovníka"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Poskytovateľ slovníka"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Služba slovníka"</string>
-    <string name="download_description" msgid="3274861514695032954">"Informácie aktualizácie slovníka"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Doplnkové slovníky"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"K dispozícii je slovník"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Nastavenia pre slovníky"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Používateľské slovníky"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Používateľský slovník"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"K dispozícii je slovník"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Aktuálne preberanie"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Nainštalovaný"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Nainštalovaný, zakázaný"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problém s pripojením k službe slovníka"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Slovníky nedostupné"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Obnoviť"</string>
-    <string name="last_update" msgid="3101549719827600346">"Posledná aktualizácia"</string>
-    <string name="message_updating" msgid="820186276704134720">"Prebieha kontrola aktualizácií"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Prebieha načítavanie..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Hlavný slovník"</string>
-    <string name="cancel" msgid="5586531736609183304">"Zrušiť"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Inštalovať"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Zrušiť preberanie"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Zakázať"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Povoliť"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Odstrániť"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"K dispozícii je slovník pre jazyk <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Stlačením skontrolujete a prevezmete"</string>
+    <string name="app_name" msgid="6320102637491234792">"Poskytovateľ slovníka"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Poskytovateľ slovníka"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Služba slovníka"</string>
+    <string name="download_description" msgid="6014835283119198591">"Informácie aktualizácie slovníka"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Doplnkové slovníky"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"K dispozícii je slovník"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Nastavenia pre slovníky"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Používateľské slovníky"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Používateľský slovník"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"K dispozícii je slovník"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Aktuálne sa preberá"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Nainštalované"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Nainštalovaný, zakázaný"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Probl. s prip. k sl."</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Slovníky sú nedostupné"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Obnoviť"</string>
+    <string name="last_update" msgid="730467549913588780">"Posledná aktualizácia"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Prebieha kontrola aktualizácií"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Načítava sa..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Hlavný slovník"</string>
+    <string name="cancel" msgid="6830980399865683324">"Zrušiť"</string>
+    <string name="install_dict" msgid="180852772562189365">"Inštalovať"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Zrušiť"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Odstrániť"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Pre vybratý jazyk mobilného zariadenia je k dispozícii slovník.&lt;br/&gt; Slovník jazyka <xliff:g id="LANGUAGE">%1$s</xliff:g> vám odporúčame &lt;b&gt;prevziať&lt;/b&gt;. Pomôže vám pri zadávaní textu.&lt;br/&gt; &lt;br/&gt; V sieti 3G môže preberanie chvíľu trvať. Ak nemáte &lt;b&gt;neobmedzený dátový program&lt;/b&gt;, môžu sa účtovať poplatky.&lt;br/&gt; Ak s určitosťou neviete aký dátový program používate, vyhľadajte pripojenie k sieti Wi-Fi a preberanie sa spustí automaticky.&lt;br/&gt; &lt;br/&gt; Tip: Slovníky môžete v mobilnom zariadení preberať a odstraňovať v časti &lt;b&gt;Jazyk a vstup&lt;/b&gt; ponuky &lt;b&gt;Nastavenia&lt;/b&gt;."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Prevziať (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Prevziať cez sieť Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"K dispozícii je slovník pre jazyk <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Stlačením skontrolujete a prevezmete"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Preberanie: návrhy pre jazyk <xliff:g id="LANGUAGE">%1$s</xliff:g> budú čoskoro k dispozícii."</string>
 </resources>
diff --git a/java/res/values-sl/strings-appname.xml b/java/res/values-sl/strings-appname.xml
deleted file mode 100644
index fd303d8..0000000
--- a/java/res/values-sl/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Tipkovnica Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Črkovalnik za Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Nastavitve tipkovnice Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Nastavitve preverjanja črkovanja"</string>
-</resources>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index 97e5518..09b0dd5 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tipkovnica Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Tipkovnica za Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Nastavitve tipkovnice za Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Črkovalnik za Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Nastavitve črkovalnika za Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti vnosa"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Ukazi za dnevnik raziskav"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Črkovalnik za Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Iskanje imen stikov"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Črkovalnik uporablja vnose s seznama stikov"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibriranje ob pritisku tipke"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. vnos je onem."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Nastavitev načinov vnosa"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Jeziki vnosa"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Pošljite povratne informacije"</string>
     <string name="select_language" msgid="3693815588777926848">"Jeziki vnosa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotaknite se še enkrat, da shranite"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovar je na voljo"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Omogoči povratne informacije uporabnikov"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"S samodejnim pošiljanjem statističnih podatkov o uporabi in poročil o zrušitvah Googlu nam lahko pomagate izboljšati urejevalnik načina vnosa."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angleščina (Združeno kraljestvo)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angleščina (ZDA)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Ne zdaj"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Isti slog vnosa že obstaja: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način za preučevanje uporabnosti"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Nastavitve zakasnitve za dolg pritisk tipke"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Nastavitve za trajanje vibriranja ob pritisku tipke"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Nastavitve za glasnost zvoka ob pritisku tipke"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Branje zunanje datoteke slovarja"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"V mapi »Prenosi« ni nobene datoteke slovarja"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Izberite datoteko slovarja, ki jo želite namestiti"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Privzeto"</string>
     <string name="language_settings" msgid="1671153053201809031">"Jezik in vnos"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Izbira načina vnosa"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Slovar"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Storitev slovarja"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Slovar"</string>
-    <string name="download_description" msgid="3274861514695032954">"Podatki o posodobitvi slovarja"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Dodatni slovarji"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Slovar je na voljo"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Nastavitve za slovarje"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Uporabniški slovar"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Uporabniški slovar"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Slovar je na voljo"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Trenutno se prenaša"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Nameščeno"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Nameščen, onemogočen"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Težava s povezavo"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Ni slovarjev"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Osveži"</string>
-    <string name="last_update" msgid="3101549719827600346">"Nazadnje posodobljeno"</string>
-    <string name="message_updating" msgid="820186276704134720">"Preverjanje, ali so na voljo posodobitve"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Nalaganje ..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Glavni slovar"</string>
-    <string name="cancel" msgid="5586531736609183304">"Prekliči"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Namesti"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Prekliči prenos"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Onemogoči"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Omogoči"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Izbriši"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Za izbran jezik v mob. napravi je na voljo slovar.&lt;br/&gt; Za izboljšano izkušnjo tipkanja priporočamo, da &lt;b&gt;prenesete&lt;/b&gt; slovar za ta jezik: <xliff:g id="LANGUAGE">%1$s</xliff:g>.&lt;br/&gt; &lt;br/&gt; Prenos prek povezave UMTS lahko traja minuto ali dve. Če nimate &lt;b&gt;neomejen. prenosa podatkov&lt;/b&gt;.&lt;br/&gt;, ga boste morda morali plačati. Če ne veste, kateri pod. paket imate, poiščite omrežje Wi-Fi, da prenos začnete samodejno.&lt;br/&gt; &lt;br/&gt; Nasvet: Slovarje lahko prenesete in odstranite tako, da v meniju &lt;b&gt;Nastavitve&lt;/b&gt; v napravi odprete &lt;b&gt;Jezik in vnos&lt;/b&gt;."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Prenesi zdaj (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Prenos prek povezave Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Slovar je na voljo za jezik <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Pritisnite za pregled in prenos"</string>
+    <string name="app_name" msgid="6320102637491234792">"Ponudnik slovarja"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Ponudnik slovarja"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Storitev slovarja"</string>
+    <string name="download_description" msgid="6014835283119198591">"Podatki o posodobitvi slovarja"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Dodatni slovarji"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Slovar je na voljo"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Nastavitve za slovarje"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Uporabniški slovarji"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Uporabniški slovar"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Slovar je na voljo"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Trenutno se prenaša"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Nameščen"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Nameščen, onemogočen"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Težava s povezavo"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Ni slovarjev"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Osveži"</string>
+    <string name="last_update" msgid="730467549913588780">"Nazadnje posodobljeno"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Iskanje posodobitev"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Nalaganje ..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Glavni slovar"</string>
+    <string name="cancel" msgid="6830980399865683324">"Prekliči"</string>
+    <string name="install_dict" msgid="180852772562189365">"Namesti"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Prekliči"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Izbriši"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Za izbrani jezik v mobilni napravi je na voljo slovar.&lt;br/&gt; Za izboljšano izkušnjo tipkanja priporočamo, da &lt;b&gt;prenesete&lt;/b&gt; slovar za ta jezik: <xliff:g id="LANGUAGE">%1$s</xliff:g>.&lt;br/&gt; &lt;br/&gt; Prenos prek povezave 3G lahko traja minuto ali dve. Če nimate &lt;b&gt;neomejenega podatkovnega paketa&lt;/b&gt;.&lt;br/&gt;, boste morda morali plačati prenos podatkov. Če ne veste, kateri podatkovni paket imate, priporočamo, da poiščete omrežje Wi-Fi in prenos začnete samodejno.&lt;br/&gt; &lt;br/&gt; Nasvet: Slovarje lahko prenesete in odstranite tako, da v meniju &lt;b&gt;Nastavitve&lt;/b&gt; v mobilni napravi odprete &lt;b&gt;Jezik in vnos&lt;/b&gt;."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Prenesi zdaj (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Prenos prek povezave Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Slovar je na voljo za jezik <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Pritisnite za pregled in prenos"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Predlogi za prenos za jezik <xliff:g id="LANGUAGE">%1$s</xliff:g> bodo kmalu pripravljeni."</string>
 </resources>
diff --git a/java/res/values-sr/strings-appname.xml b/java/res/values-sr/strings-appname.xml
deleted file mode 100644
index 449fe55..0000000
--- a/java/res/values-sr/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android тастатура"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android провера правописа"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Подешавања Android тастатуре"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Подешавања провере правописа"</string>
-</resources>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 9b30223..91c9346 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android тастатура (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android тастатура (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Подешавања Android тастатуре (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android провера правописа (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Подешавања Android провере правописа (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Опције уноса"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Команде евиденције истраживања"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android провера правописа (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Потражи имена контаката"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Контролор правописа користи уносе са листе контаката"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вибрирај на притисак тастера"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Гласовни унос је онемогућен"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Конфигурисање метода уноса"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Језици за унос"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Пошаљи повратне информације"</string>
     <string name="select_language" msgid="3693815588777926848">"Језици уноса"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Поново додирните да бисте сачували"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Речник је доступан"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Омогући повратну информацију корисника"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Помозите да се побољша овај уређивач режима уноса тако што ће се аутоматски послати статистика о коришћењу и извештаји о грешкама компанији Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема тастатуре"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"енглески (УК)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"енглески (САД)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Не сада"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Исти стил уноса већ постоји: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим за студију могућности коришћења"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Подешавања одлагања при дугом притиску на тастер"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Подешавања трајања вибрације при притиску на тастере"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Подешавања јачине звука при притиску на тастере"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Читање датотеке спољног речника"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"У директоријуму Преузимања нема датотека речника"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Избор датотеке речника за инсталирање"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Подразумевано"</string>
     <string name="language_settings" msgid="1671153053201809031">"Језик и унос"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Избор метода уноса"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Добављач речника"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Добављач речника"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Услуга речника"</string>
-    <string name="download_description" msgid="3274861514695032954">"Информације о ажурирању речника"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Помоћни речници"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Речник је доступан"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Подешавања за речнике"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Кориснички речници"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Кориснички речник"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Речник је доступан"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Тренутно се преузима"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Инсталирано"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Инсталиран, онемогућен"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Нема услуге речника"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Нема доступних речника"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Освежи"</string>
-    <string name="last_update" msgid="3101549719827600346">"Последње ажурирање"</string>
-    <string name="message_updating" msgid="820186276704134720">"Тражење ажурирања"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Учитавање..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Главни речник"</string>
-    <string name="cancel" msgid="5586531736609183304">"Откажи"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Инсталирај"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Откажи преузимање"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Онемогући"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Омогући"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Избриши"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Речник је доступан за <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Притисните за преглед и преузимање"</string>
+    <string name="app_name" msgid="6320102637491234792">"Добављач речника"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Добављач речника"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Услуга речника"</string>
+    <string name="download_description" msgid="6014835283119198591">"Информације о ажурирању речника"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Помоћни речници"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Речник је доступан"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Подешавања за речнике"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Кориснички речници"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Кориснички речник"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Речник је доступан"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Тренутно се преузима"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Инсталиран је"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Инсталиран је и онемогућен"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Проблем при повезивању с услугом речника"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Нема доступних речника"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Освежи"</string>
+    <string name="last_update" msgid="730467549913588780">"Последње ажурирање"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Тражење ажурирања"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Учитавање..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Главни речник"</string>
+    <string name="cancel" msgid="6830980399865683324">"Откажи"</string>
+    <string name="install_dict" msgid="180852772562189365">"Инсталирај"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Откажи"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Избриши"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Доступан је речник за изабрани језик на мобилном уређају.&lt;br/&gt; Препоручујемо да &lt;b&gt;преузмете &lt;/b&gt; речник за <xliff:g id="LANGUAGE">%1$s</xliff:g> да бисте побољшали доживљај куцања.&lt;br/&gt; &lt;br/&gt; Преузимање може да траје минут или два преко 3G мреже. Трошкови ће можда бити наплаћени ако немате &lt;b&gt;претплатнички пакет без ограничења&lt;/b&gt;.&lt;br/&gt; Ако нисте сигурни који претплатнички пакет имате, препоручујемо да пронађете Wi-Fi везу да бисте аутоматски започели преузимање.&lt;br/&gt; &lt;br/&gt; Савет: Речнике можете да преузимате и уклањате тако што ћете посетити &lt;b&gt;Језик и унос&lt;/b&gt; у менију &lt;b&gt;Подешавања&lt;/b&gt; мобилног уређаја."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Преузми одмах (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Преузми преко Wi-Fi-ја"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Речник је доступан за <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Притисните за преглед и преузимање"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Преузимање: Предлози за <xliff:g id="LANGUAGE">%1$s</xliff:g> ће ускоро бити спремни."</string>
 </resources>
diff --git a/java/res/values-sv/strings-appname.xml b/java/res/values-sv/strings-appname.xml
deleted file mode 100644
index 9b4a7db..0000000
--- a/java/res/values-sv/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Androids tangentbord"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Stavningskontroll i Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Inställningar för Androids tangentbord"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Inställningar för stavningskontroll"</string>
-</resources>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 24ea428..643302a 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androids tangentbord (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androids tangentbord (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Inställningar för Androids tangentbord (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Stavningskontroll i Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Inställningar för Androids stavningskontroll (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Inmatningsalternativ"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Loggkommandon"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Stavningskontroll i Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Sök namn på kontakter"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"I stavningskontrollen används poster från kontaktlistan"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrera vid tangenttryck"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Röstinmatning inaktiv"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurera inmatningsmetoder"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Inmatningsspråk"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Skicka feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Inmatningsspråk"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Spara genom att trycka igen"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"En ordlista är tillgänglig"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Aktivera synpunkter från användare"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Du kan hjälpa till att förbättra inmatningsmetoden genom att automatiskt skicka användningsstatistik och felrapporter till Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tangentbordstema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelskt (brittiskt)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelskt (amerikanskt)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Inte nu"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Samma indatastil finns redan: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Läge för studie av användbarhet"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Inställningar för fördröjning vid långt tryck"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Inställningar för vibrationslängd vid knapptryck"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volyminställningar för knappljud"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Läs extern ordboksfil"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Inga ordboksfiler i mappen Hämtningar"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Välj en ordboksfil att installera"</string>
@@ -170,36 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="language_settings" msgid="1671153053201809031">"Språk &amp; inmatning"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Välj inmatningsmetod"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Dictionary Provider"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Dictionary Provider"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Ordbokstjänst"</string>
-    <string name="download_description" msgid="3274861514695032954">"Uppdateringsinformation för ordlista"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Tilläggsordlistor"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"En ordlista är tillgänglig"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Inställningar för ordlistor"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Egna ordlistor"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Egen ordlista"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"En ordlista är tillgänglig"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Hämtas för närvarande"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Installerad"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Installerad, inaktiverad"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problem med att ansluta till ordlistetjänsten"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Det finns inga ordböcker"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Uppdatera"</string>
-    <string name="last_update" msgid="3101549719827600346">"Senast uppdaterad"</string>
-    <string name="message_updating" msgid="820186276704134720">"Söker efter uppdateringar"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Läser in ..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Huvudordlistan"</string>
-    <string name="cancel" msgid="5586531736609183304">"Avbryt"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Installera"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Avbryt hämtning"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Inaktivera"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Aktivera"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Ta bort"</string>
-    <string name="should_download_over_metered_prompt" msgid="4965264849057656521">"Det finns en ordlista för språket du har valt i enheten.&lt;br/&gt; Vi rekommenderar att du &lt;b&gt;hämtar&lt;/b&gt; den <xliff:g id="LANGUAGE">%1$s</xliff:g> ordlistan.&lt;br/&gt; &lt;br/&gt; Det kan ta någon minut att hämta den över 3G. Avgifter kan tillkomma om du inte har ett abonnemang med &lt;b&gt;obegränsad datatrafik&lt;/b&gt;.&lt;br/&gt; Om du är osäker på ditt abonnemang rekommenderar vi att du ansluter till ett Wi-Fi-nätverk och hämtar ordlistan automatiskt.&lt;br/&gt; &lt;br/&gt; Tips! Du kan hämta och ta bort ordlistor under &lt;b&gt;Språk och inmatning&lt;/b&gt; i menyn &lt;b&gt;Inställningar&lt;/b&gt; på enheten."</string>
-    <string name="download_over_metered" msgid="4024013764937850061">"Hämta nu (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="6963770885033765378">"Hämta över Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"En ordlista är tillgänglig för <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Tryck om du vill granska och hämta"</string>
+    <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Ordlistetjänst"</string>
+    <string name="download_description" msgid="6014835283119198591">"Uppdateringsinformation för ordlista"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Tilläggsordlistor"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"En ordlista är tillgänglig"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Inställningar för ordlistor"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Egna ordlistor"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Egen ordlista"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"En ordlista är tillgänglig"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Hämtar för närvarande"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installerad"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installerad, inaktiverad"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Problem med att ansluta till ordlistetjänsten"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Inga ordlistor finns"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Uppdatera"</string>
+    <string name="last_update" msgid="730467549913588780">"Informationen uppdaterades senast"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Söker efter uppdateringar"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Läser in ..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Huvudordlista"</string>
+    <string name="cancel" msgid="6830980399865683324">"Avbryt"</string>
+    <string name="install_dict" msgid="180852772562189365">"Installera"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Avbryt"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Ta bort"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Det finns en ordlista för språket du har valt i din mobila enhet.&lt;br/&gt; Vi rekommenderar att du &lt;b&gt;hämtar&lt;/b&gt; ordlistan för <xliff:g id="LANGUAGE">%1$s</xliff:g> så att det blir enklare att skriva.&lt;br/&gt; &lt;br/&gt; Det kan ta någon minut att hämta den via 3G. Avgifter kan tillkomma om du inte har ett abonnemang med &lt;b&gt;obegränsad datatrafik&lt;/b&gt;.&lt;br/&gt; Om du är osäker på vilket abonnemang du har rekommenderar vi att du ansluter till ett Wi-Fi-nätverk och hämtar ordlistan automatiskt.&lt;br/&gt; &lt;br/&gt; Tips! Du kan hämta och ta bort ordlistor under &lt;b&gt;Språk och inmatning&lt;/b&gt; i menyn &lt;b&gt;Inställningar&lt;/b&gt; på den mobila enheten."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Hämta nu (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Hämta via Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"En ordlista är tillgänglig för <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Tryck om du vill granska och hämta"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Hämtar: förslag för <xliff:g id="LANGUAGE">%1$s</xliff:g> är snart klara."</string>
 </resources>
diff --git a/java/res/values-sw/strings-appname.xml b/java/res/values-sw/strings-appname.xml
deleted file mode 100644
index 51de0a6..0000000
--- a/java/res/values-sw/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Kibodi ya Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Kikagua tahajia cha Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Mipangilio ya kibodi ya Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Mipangilio ya kukagua tahajia"</string>
-</resources>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index a974753..a461795 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Kicharazio cha Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Kibodi ya Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Mipangilio ya Kibodi ya Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Kikagua-tahajia cha Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Mipangilio ya Kikagua-tahajia cha Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Amri za Kumbukumbu za Utafiti"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kikagua tahajia cha Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya unaowasiliana nao"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kikagua tahajia hutumia ingizo kutoka kwa orodha yako ya anwani"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string>
@@ -89,7 +91,7 @@
     <string name="spoken_description_delete" msgid="8740376944276199801">"Futa"</string>
     <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Alama"</string>
     <string name="spoken_description_to_alpha" msgid="23129338819771807">"Herufi"</string>
-    <string name="spoken_description_to_numeric" msgid="591752092685161732">"Namba"</string>
+    <string name="spoken_description_to_numeric" msgid="591752092685161732">"Nambari"</string>
     <string name="spoken_description_settings" msgid="4627462689603838099">"Mipangilio"</string>
     <string name="spoken_description_tab" msgid="2667716002663482248">"Kichupo"</string>
     <string name="spoken_description_space" msgid="2582521050049860859">"Nafasi"</string>
@@ -113,7 +115,7 @@
     <string name="keyboard_mode_date" msgid="3137520166817128102">"tarehe"</string>
     <string name="keyboard_mode_date_time" msgid="339593358488851072">"tarehe na wakati"</string>
     <string name="keyboard_mode_email" msgid="6216248078128294262">"barua pepe"</string>
-    <string name="keyboard_mode_im" msgid="1137405089766557048">"inatuma ujumbe"</string>
+    <string name="keyboard_mode_im" msgid="1137405089766557048">"Utumaji ujumbe"</string>
     <string name="keyboard_mode_number" msgid="7991623440699957069">"nambari"</string>
     <string name="keyboard_mode_phone" msgid="6851627527401433229">"simu"</string>
     <string name="keyboard_mode_text" msgid="6479436687899701619">"maandishi"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Uingizaji sauti umelemazwa"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Sanidi mbinu za uingizaji"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Lugha za uingizaji"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Tuma maoni"</string>
     <string name="select_language" msgid="3693815588777926848">"Lugha zinazoruhusiwa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gusa tena ili kuhifadhi"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamusi inapatikana"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Wezesha maoni ya watumiaji"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Saidia kuimarisha mbinu ya uingizaji wa kihariri, kwa kutuma takwimu za matumizi na ripoti za kuvurugika kwa Google kiotomatiki."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Maandhari ya kibodi"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Kiingereza cha (Uingereza)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Kiingereza cha (Marekani)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Sio sasa"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Mfumo sawa wa maingizo tayari upo: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modi ya uchunguzi wa utumizi"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"mipangilio ya kuchelewesha kwa kubonyeza kitufe kwa muda mrefu"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Bonyeza mipangilio ya kipindi cha mtetemo"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Bonyeza mipangilio ya nguvu za sauti"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Soma faili ya kamusi ya nje"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Hakuna faili za kamusi katika folda ya Vilivyopakuliwa"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Chagua faili ya kamusi ya kusakinisha"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Chaguo-msingi"</string>
     <string name="language_settings" msgid="1671153053201809031">"Lugha na uingizaji"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Chagua mbinu ya kuingiza data"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Mtoaji Kamusi"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Mtoaji Kamusi"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Huduma ya Kamusi"</string>
-    <string name="download_description" msgid="3274861514695032954">"Maelezo ya kusasisha kamusi"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Nyongeza za kamusi"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Kamusi inapatikana"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Mipangilio ya kamusi"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Kamusi ya mtumiaji"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Kamusi ya mtumiaji"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Kamusi inapatikana"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Inapakua sasa"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Imesakinishwa"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"kusakinisha, imelemazwa"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Tatizo kuunganisha kwa huduma ya kamusi"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Hakuna kamusi inapatikana"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Zimua"</string>
-    <string name="last_update" msgid="3101549719827600346">"Mara ya mwisho kusasishwa"</string>
-    <string name="message_updating" msgid="820186276704134720">"Inatafuta visasishi..."</string>
-    <string name="message_loading" msgid="8611339149825047446">"Inapakia..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Kamusi kuu"</string>
-    <string name="cancel" msgid="5586531736609183304">"Katisha"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Sakinisha"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Ghairi kupakua"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Lemaza"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Wezesha"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Futa"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Kamusi inapatikana ya <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Bonyeza ili kukagua na kupakua"</string>
+    <string name="app_name" msgid="6320102637491234792">"Mtoaji Kamusi"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Mtoaji Kamusi"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Huduma ya Kamusi"</string>
+    <string name="download_description" msgid="6014835283119198591">"Maelezo ya kusasisha kamusi"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Kamusi za nyongeza"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Kamusi inapatikana"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Mipangilio ya kamusi"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Kamusi ya mtumiaji"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Kamusi ya mtumiaji"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Kamusi inapatikana"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Inapakua sasa"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Imesakinishwa"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Imesakinishwa, haitumiki"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Tatizo wakati wa kuunganisha kwenye huduma ya kamusi"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Hakuna kamusi inayopatikana"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Onyesha upya"</string>
+    <string name="last_update" msgid="730467549913588780">"Ilibadilishwa mwisho"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Inatafuta sasisho..."</string>
+    <string name="message_loading" msgid="8689096636874758814">"Inapakia..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Kamusi kuu"</string>
+    <string name="cancel" msgid="6830980399865683324">"Ghairi"</string>
+    <string name="install_dict" msgid="180852772562189365">"Sakinisha"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Ghairi"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Futa"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Lugha iliyochaguliwa kwenye kifaa chako cha mkononi ina kamusi inayopatikana.&lt;br/&gt; Tunapendekeza&lt;b&gt;upakuaji wa kamusi&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> ili kuboresha hali yako ya kucharaza.&lt;br/&gt; &lt;br/&gt; Upakuaji unaweza kuchukua dakika moja au mbili kukamilika kwenye 3G. Unaweza kutozwa pesa ikiwa huna mpango wa data &lt;b&gt;usio na kipimo &lt;/b&gt;.&lt;br/&gt;Ikiwa huna uhakika una mpango gani wa data, tunapendekeza utafute muunganisho wa Wi-Fi ili uanze upakuaji moja kwa moja.&lt;br/&gt; &lt;br/&gt; Kidokezo: Unaweza kupakua na kuondoa kamusi kwa kuenda kwenye&lt;b&gt;Ingizo la &amp; Lugha&lt;/b&gt; katika &lt;b&gt;menyu ya Mipangilio&lt;/b&gt; ya kifaa chako cha mkononi."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Pakua sasa (MB<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Pakua kwenye Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Kamusi ya <xliff:g id="LANGUAGE">%1$s</xliff:g> inapatikana"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Bonyeza ili kukagua na kupakua"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Inapakua: mapendekezo ya <xliff:g id="LANGUAGE">%1$s</xliff:g> yatakuwa tayari hivi karibuni."</string>
 </resources>
diff --git a/java/res/values-th/strings-appname.xml b/java/res/values-th/strings-appname.xml
deleted file mode 100644
index 7fc7e3e..0000000
--- a/java/res/values-th/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"แป้นพิมพ์แอนดรอยด์"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"การตรวจสอบการสะกดของแอนดรอยด์"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"การตั้งค่าแป้นพิมพ์แอนดรอยด์"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"การตั้งค่าการตรวจสอบการสะกด"</string>
-</resources>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 2cf9130..5279e30 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"แป้นพิมพ์แอนดรอยด์ (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"การตั้งค่าแป้นพิมพ์แอนดรอยด์ (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"เครื่องตรวจตัวสะกดแอนดรอยด์ (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"การตั้งค่าเครื่องตรวจตัวสะกดแอนดรอยด์ (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"ตัวเลือกการป้อนข้อมูล"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"คำสั่งบันทึกการวิจัย"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"แอนดรอยด์ตรวจสอบการสะกด (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"ค้นหารายชื่อติดต่อ"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"เครื่องมือตรวจการสะกดใช้รายการจากรายชื่อติดต่อของคุณ"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"สั่นเมื่อกดปุ่ม"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ปิดใช้งานป้อนข้อมูลด้วยเสียง"</string>
     <string name="configure_input_method" msgid="373356270290742459">"กำหนดค่าวิธีการป้อนข้อมูล"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"ภาษาในการป้อนข้อมูล"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"ส่งข้อเสนอแนะ"</string>
     <string name="select_language" msgid="3693815588777926848">"ภาษาสำหรับการป้อนข้อมูล"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"แตะอีกครั้งเพื่อบัน​​ทึก"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"มีพจนานุกรมให้ใช้งาน"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"เปิดใช้งานการแสดงความคิดเห็นจากผู้ใช้"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"ช่วยปรับปรุงตัวแก้ไขวิธีการป้อนข้อมูลนี้โดยการส่งสถิติการใช้งานและรายงานการขัดข้องถึง Google โดยอัตโนมัติ"</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"ชุดรูปแบบแป้นพิมพ์"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"อังกฤษ (สหราชอาณาจักร)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"อังกฤษ (อเมริกัน)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"ข้ามไปก่อน"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"รูปแบบการป้อนข้อมูลเดียวกันนี้มีอยู่แล้ว: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"โหมดศึกษาประโยชน์ในการใช้งาน"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"การตั้งค่าความหน่วงของการกดแป้นค้าง"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"การตั้งค่าระยะเวลาการสั่นเมื่อกดแป้นพิมพ์"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"การตั้งค่าระดับเสียงเมื่อกดแป้นพิมพ์"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"อ่านไฟล์พจนานุกรมภายนอก"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"ไม่มีไฟล์พจนานุกรมในโฟลเดอร์ดาวน์โหลด"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"เลือกไฟล์พจนานุกรมที่จะติดตั้ง"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"ค่าเริ่มต้น"</string>
     <string name="language_settings" msgid="1671153053201809031">"ภาษาและการป้อนข้อมูล"</string>
     <string name="select_input_method" msgid="4301602374609275003">"เลือกวิธีการป้อนข้อมูล"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"ผู้ให้บริการพจนานุกรม"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"ผู้ให้บริการพจนานุกรม"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"บริการพจนานุกรม"</string>
-    <string name="download_description" msgid="3274861514695032954">"ข้อมูลอัปเดตสำหรับพจนานุกรม"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"พจนานุกรม Add-On"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"มีพจนานุกรมให้ใช้งาน"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"การตั้งค่าสำหรับพจนานุกรม"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"พจนานุกรมผู้ใช้"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"พจนานุกรมผู้ใช้"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"มีพจนานุกรมให้ใช้งาน"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"กำลังดาวน์โหลดอยู่"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"ติดตั้งแล้ว"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"ติดตั้งแล้วแต่ปิดใช้งาน"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"พบปัญหาขณะเชื่อมต่อ"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"ไม่มีพจนานุกรม"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"รีเฟรช"</string>
-    <string name="last_update" msgid="3101549719827600346">"ปรับปรุงล่าสุดเมื่อ"</string>
-    <string name="message_updating" msgid="820186276704134720">"กำลังตรวจสอบการอัปเดต..."</string>
-    <string name="message_loading" msgid="8611339149825047446">"กำลังโหลด..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"พจนานุกรมหลัก"</string>
-    <string name="cancel" msgid="5586531736609183304">"ยกเลิก"</string>
-    <string name="install_dict" msgid="5525005524697607865">"ติดตั้ง"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"ยกเลิกการดาวน์โหลด"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"ปิดใช้งาน"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"เปิดใช้งาน"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"ลบ"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"มีพจนานุกรมให้ใช้งานในภาษา <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"กดเพื่อตรวจสอบและดาวน์โหลด"</string>
+    <string name="app_name" msgid="6320102637491234792">"ผู้ให้บริการพจนานุกรม"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"ผู้ให้บริการพจนานุกรม"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"บริการพจนานุกรม"</string>
+    <string name="download_description" msgid="6014835283119198591">"ข้อมูลอัปเดตสำหรับพจนานุกรม"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"พจนานุกรมส่วนเสริม"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"มีพจนานุกรมให้ใช้งาน"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"การตั้งค่าสำหรับพจนานุกรม"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"พจนานุกรมผู้ใช้"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"พจนานุกรมผู้ใช้"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"มีพจนานุกรมให้ใช้งาน"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"กำลังดาวน์โหลดอยู่"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"ติดตั้งแล้ว"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"ติดตั้งแล้วแต่ปิดใช้งาน"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"พบปัญหาขณะเชื่อมต่อ"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"ไม่มีพจนานุกรม"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"รีเฟรช"</string>
+    <string name="last_update" msgid="730467549913588780">"ปรับปรุงแก้ไขครั้งล่าสุด"</string>
+    <string name="message_updating" msgid="4457761393932375219">"กำลังตรวจสอบการอัปเดต"</string>
+    <string name="message_loading" msgid="8689096636874758814">"กำลังโหลด..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"พจนานุกรมหลัก"</string>
+    <string name="cancel" msgid="6830980399865683324">"ยกเลิก"</string>
+    <string name="install_dict" msgid="180852772562189365">"ติดตั้ง"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"ยกเลิก"</string>
+    <string name="delete_dict" msgid="756853268088330054">"ลบ"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"ภาษาที่คุณเลือกใช้ในอุปกรณ์เคลื่อนที่มีพจนานุกรมที่สามารถใช้ได้&lt;br/&gt; เราขอแนะนำให้คุณ &lt;b&gt;ดาวน์โหลด&lt;/b&gt; พจนานุกรม <xliff:g id="LANGUAGE">%1$s</xliff:g> เพื่อรับประสบการณ์การพิมพ์ที่ดียิ่งขึ้น&lt;br/&gt; &lt;br/&gt;การดาวน์โหลดจะใช้เวลาหนึ่งถึงสองนาทีผ่านทาง 3G ซึ่งอาจมีการเรียกเก็บเงินหากคุณไม่ได้ใช้ &lt;b&gt;แผนบริการข้อมูลแบบไม่จำกัดปริมาณ&lt;/b&gt; &lt;br/&gt;หากคุณไม่แน่ใจว่าคุณใช้แผนบริการข้อมูลแบบใด เราขอแนะนำให้คุณเชื่อมต่อ WiFi เพื่อเริ่มการดาวน์โหลดอัตโนมัติ&lt;br/&gt; &lt;br/&gt;เคล็ดลับ: คุณสามารถดาวน์โหลดและนำพจนานุกรมออกได้โดยไปที่ &lt;b&gt;ภาษาและการป้อนข้อมูล&lt;/b&gt; ในเมนู &lt;b&gt;การตั้งค่า&lt;/b&gt; ในอุปกรณ์เคลื่อนที่ของคุณ"</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"ดาวน์โหลดเลย (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"ดาวน์โหลดผ่าน WiFi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"มีพจนานุกรมให้ใช้งานในภาษา <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"กดเพื่อตรวจสอบและดาวน์โหลด"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"กำลังดาวน์โหลด: คำแนะนำสำหรับ <xliff:g id="LANGUAGE">%1$s</xliff:g> จะพร้อมใช้งานเร็วๆ นี้"</string>
 </resources>
diff --git a/java/res/values-tl/strings-appname.xml b/java/res/values-tl/strings-appname.xml
deleted file mode 100644
index fd2b3f5..0000000
--- a/java/res/values-tl/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Keyboard ng Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Spell checker ng Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Mga setting ng keyboard ng Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Mga setting ng pag-spell check"</string>
-</resources>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index ad5714d..11918d3 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android Keyboard (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Mga Setting ng Android Keyboard (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Spell Checker ng Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Mga Setting ng Spell Checker ng Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Mga pagpipilian sa input"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Cmmnd sa Log ng Pnnliksik"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pang-check ng pagbabaybay ng Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Maghanap pangalan contact"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Gumagamit pang-check pagbabaybay entry sa iyong listahan contact"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Mag-vibrate sa keypress"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hindi pinagana ang voice input"</string>
     <string name="configure_input_method" msgid="373356270290742459">"I-configure ang mga pamamaraan ng pag-input"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Mag-input ng mga wika"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Magpadala ng feedback"</string>
     <string name="select_language" msgid="3693815588777926848">"Mga wika ng input"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pinduting muli upang i-save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Available ang diksyunaryo"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Paganahin ang feedback ng user"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Tumulong na pahusayin ang editor ng paraan ng pag-input na ito sa pamamagitan ng awtomatikong pagpapadala ng mga istatistika ng paggamit at mga ulat ng crash sa Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema ng keyboard"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Ingles (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Ingles (Estados Unidos)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Hindi ngayon"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Umiiral na ang parehong estilo ng input: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Study mode ng pagiging kapaki-pakinabang"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Mga setting ng pagkaantala ng matagal na pagpindot sa key"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Mga setting ng tagal ng vibration ng keypress"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Mga setting ng volume ng tunog ng keypress"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Magbasa ng panlabas na file ng diksyunaryo"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Walang mga file ng diksyunaryo sa folder na Mga Download"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pumili ng file ng diksyunaryo na ii-install"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Default"</string>
     <string name="language_settings" msgid="1671153053201809031">"Wika at input"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Pumili ng pamamaraan ng pag-input"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Provider ng Diksyunaryo"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Provider ng Diksyunaryo"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Serbisyo ng Diksyunaryo"</string>
-    <string name="download_description" msgid="3274861514695032954">"Impormasyon ng pag-update sa diksyunaryo"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Mga diksyunaryo na add-on"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Available ang diksyunaryo"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Mga setting para sa mga diksyunaryo"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Mga diksyunaryo ng user"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Diksyunaryo ng user"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Available ang diksyunaryo"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Kasalukuyang nagda-download"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Naka-install"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Naka-install, hindi pinagana"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Problema sa pagkonekta sa serbisyo ng diksyunaryo"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Walang available na mga diksyunaryo"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"I-refresh"</string>
-    <string name="last_update" msgid="3101549719827600346">"Huling na-update"</string>
-    <string name="message_updating" msgid="820186276704134720">"Tumitingin ng mga update"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Naglo-load..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Pangunahing diksyunaryo"</string>
-    <string name="cancel" msgid="5586531736609183304">"Kanselahin"</string>
-    <string name="install_dict" msgid="5525005524697607865">"I-install"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Kanselahin ang pag-download"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Huwag paganahin"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Paganahin"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Tanggalin"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Available ang isang diksyunaryo para sa <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Pindutin upang suriin at i-download"</string>
+    <string name="app_name" msgid="6320102637491234792">"Provider ng Diksyunaryo"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Provider ng Diksyunaryo"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Serbisyo ng Diksyunaryo"</string>
+    <string name="download_description" msgid="6014835283119198591">"Impormasyon ng update sa diksyunaryo"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Mga add-on na diksyunaryo"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Available ang diksyunaryo"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Mga setting para sa mga diksyunaryo"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Mga diksyunaryo ng user"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Diksyunaryo ng user"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Available ang diksyunaryo"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Kasalukuyang dina-download"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Na-install na"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Naka-install, hindi pinagana"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Di makakonekta sa serbisyong diksyunaryo"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Walang mga diksyunaryo"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"I-refresh"</string>
+    <string name="last_update" msgid="730467549913588780">"Huling na-update"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Tumitingin ng mga update"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Naglo-load..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Pangunahing diksyunaryo"</string>
+    <string name="cancel" msgid="6830980399865683324">"Kanselahin"</string>
+    <string name="install_dict" msgid="180852772562189365">"I-install"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Kanselahin"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Tanggalin"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"May available na diksyunaryo ang piniling wika sa iyong mobile device.&lt;br/&gt; Inirerekomenda namin ang &lt;b&gt;pag-download&lt;/b&gt; sa diksyunaryong <xliff:g id="LANGUAGE">%1$s</xliff:g> upang mapabuti ang iyong karanasan sa pag-type.&lt;br/&gt; &lt;br/&gt; Maaaring umabot ng isa hanggang dalawang minuto ang pag-download gamit ang 3G. Maaaring may malapat na mga pagsingil kung wala kang &lt;b&gt;data plan na walang limitasyon&lt;/b&gt;.&lt;br/&gt; Kung hindi ka sigurado kung aling data plan ang mayroon ka, inirerekomenda naming maghanap ng koneksyon sa Wi-Fi upang awtomatikong simulan ang pag-download.&lt;br/&gt; &lt;br/&gt; Tip: Maaari kang mag-download at mag-alis ng mga diksyunaryo sa pamamagitan ng pagpunta sa &lt;b&gt;Wika at input&lt;/b&gt; sa menu na &lt;b&gt;Mga Setting&lt;/b&gt; ng iyong mobile device."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"I-download ngayon (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"I-download gamit ang Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"May available na diksyunaryo para sa <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Pindutin upang suriin at i-download"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Dina-download: malapit nang maging handa ang mga suhestiyon para sa <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-tr/strings-appname.xml b/java/res/values-tr/strings-appname.xml
deleted file mode 100644
index f5e36d2..0000000
--- a/java/res/values-tr/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android klavyesi"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android yazım denetleyici"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android klavye ayarları"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Yazım denetimi ayarları"</string>
-</resources>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 7e122ad..38185bb 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android klavye (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android klavye (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android Klavye Ayarları (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android Yazım Denetleyici (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android Yazım Denetleyici Ayarları (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Giriş seçenekleri"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Araştırma Günlüğü Komutları"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android yazım denetleyici (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kişi adlarını denetle"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Yazım denetleyici, kişi listenizdeki girişleri kullanır"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tuşa basıldığında titret"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Sesle grş devre dışı"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Giriş yöntemlerini yapılandır"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Giriş dilleri"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Geri bildirim gönder"</string>
     <string name="select_language" msgid="3693815588777926848">"Giriş dilleri"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Kaydetmek için tekrar dokunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sözlük kullanılabilir"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Kullanıcı geri bildirimini etkinleştir"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Kullanım istatistiklerini ve kilitlenme raporlarını Google\'a otomatik olarak göndererek bu giriş yöntemi düzenleyicisinin iyileştirilmesine yardımcı olun."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Klavye teması"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"İngilizce (BK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"İngilizce (ABD)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Şimdi değil"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Aynı giriş stili zaten var: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kullanılabilirlik çalışması modu"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Tuşa uzun basma için gecikme ayarları"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Tuşa basma titreşim süresi ayarları"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Tuşa basma ses düzeyi ayarları"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Harici sözlük dosyasını oku"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"İndirilenler klasöründe sözlük dosyası yok"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Yüklemek için bir sözlük dosyası seçin"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Varsayılan"</string>
     <string name="language_settings" msgid="1671153053201809031">"Dil ve giriş"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Giriş yöntemini seçin"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Sözlük Sağlayıcı"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Sözlük Sağlayıcı"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Sözlük Hizmeti"</string>
-    <string name="download_description" msgid="3274861514695032954">"Sözlük güncelleme bilgileri"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Ekli sözlükler"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Kullanılabilecek sözlük var"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Sözlükler için ayarlar"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Kullanıcı sözlükleri"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Kullanıcı sözlüğü"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Sözlük kullanılabilir"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Şu anda indiriliyor"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Yüklendi"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Yüklendi, devre dışı"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Sözlük hizmetine bağlantı yok"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Kullanılabilir sözlük yok"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Yenile"</string>
-    <string name="last_update" msgid="3101549719827600346">"Son güncelleme tarihi"</string>
-    <string name="message_updating" msgid="820186276704134720">"Güncellemeler denetleniyor..."</string>
-    <string name="message_loading" msgid="8611339149825047446">"Yükleniyor..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Ana sözlük"</string>
-    <string name="cancel" msgid="5586531736609183304">"İptal"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Yükle"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"İndirmeyi iptal et"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Devre dışı bırak"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Etkinleştir"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Sil"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"<xliff:g id="LANGUAGE">%1$s</xliff:g> için kullanılabilecek bir sözlük var"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"İncelemek ve indirmek için tıklayın"</string>
+    <string name="app_name" msgid="6320102637491234792">"Sözlük Sağlayıcı"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Sözlük Sağlayıcı"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Sözlük Hizmeti"</string>
+    <string name="download_description" msgid="6014835283119198591">"Sözlük güncelleme bilgileri"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Ek sözlükler"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Sözlük mevcut"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Sözlükler için ayarlar"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Kullanıcı sözlükleri"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Kullanıcı sözlüğü"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Sözlük mevcut"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Şu anda indiriliyor"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Yüklendi"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Yüklendi, devre dışı bırakıldı"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Sözlük hizmetine bağlantı sorunu"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Kullanılabilir sözlük yok"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Yenile"</string>
+    <string name="last_update" msgid="730467549913588780">"Son güncelleme tarihi"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Güncellemeler denetleniyor"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Yükleniyor..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Ana sözlük"</string>
+    <string name="cancel" msgid="6830980399865683324">"İptal"</string>
+    <string name="install_dict" msgid="180852772562189365">"Yükle"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"İptal"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Sil"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Mobil cihazınızda seçili dile ait kullanılabilir bir sözlük mevcut.&lt;br/&gt; Daha iyi yazabilmek için bu <xliff:g id="LANGUAGE">%1$s</xliff:g> sözlüğü &lt;b&gt;indirmenizi&lt;/b&gt; öneririz.&lt;br/&gt; &lt;br/&gt; İndirme işlemi 3G üzerinden bir veya iki dakika sürebilir. &lt;b&gt;Sınırsız veri planınız&lt;/b&gt; yoksa ücret alınabilir.&lt;br/&gt; Ne tür bir veri planına sahip olduğunuzdan emin değilseniz, otomatik olarak indirmeye başlamak için bir Kablosuz bağlantı bulmanızı öneririz.&lt;br/&gt; &lt;br/&gt; İpucu: Sözlükleri, mobil cihazınızın &lt;b&gt;Ayarlar&lt;/b&gt; menüsünde &lt;b&gt;Dil ve giriş&lt;/b&gt; seçeneğine giderek indirebilir ve silebilirsiniz."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Hemen indir (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Kablosuz üzerinden indir"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g> için kullanılabilecek bir sözlük mevcut"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"İncelemek ve indirmek için basın"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"<xliff:g id="LANGUAGE">%1$s</xliff:g> için önerilerin indirilmesine kısa süre içinde başlanacak."</string>
 </resources>
diff --git a/java/res/values-uk/strings-appname.xml b/java/res/values-uk/strings-appname.xml
deleted file mode 100644
index fdbb89f..0000000
--- a/java/res/values-uk/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Клавіатура Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Засіб перевірки орфографії Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Налаштування клавіатури Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Налаштування перевірки орфографії"</string>
-</resources>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 609c80b..30a37c2 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавіатура Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавіатура Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Налаштування клавіатури Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Перевірка орфографії Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Налаштування перевірки орфографії Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Парам. введення"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Команди журналу дослідж."</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Засіб перевірки орфографії Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукати імена контактів"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Програма перевірки правопису використ. записи зі списку контактів"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібр. при натисканні клавіш"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голос. ввід вимкнено"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Налаштування методів введення"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Мови вводу"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Надіслати відгук"</string>
     <string name="select_language" msgid="3693815588777926848">"Мови введення"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Торкніться знову, щоб зберегти"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Словник доступний"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Увімк. відгуки корист."</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Допоможіть покращ. редактор методу введ., автомат. надсилаючи в Google статистику використ. та звіти про збої."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавіатури"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Англійська (Великобританія)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Англійська (США)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Не зараз"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Такий стиль введення вже існує: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим вивчення зручності у використанні"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Налаштування довгого натискання"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Налаштування тривалості вібрації під час натискання клавіші"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Налаштування гучності звуку під час натискання клавіші"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Читати файл зовнішнього словника"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"У папці \"Завантаження\" немає файлів словника"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Вибрати файл словника, який потрібно встановити"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"За умовчанням"</string>
     <string name="language_settings" msgid="1671153053201809031">"Мова та введення"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Вибрати метод введення"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Постачальник словника"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Постачальник словника"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Послуга словника"</string>
-    <string name="download_description" msgid="3274861514695032954">"Інформація про оновлення словника"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Додаткові словники"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Словник доступний"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Налаштування для словників"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Словники користувача"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Словник користувача"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Словник доступний"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Зараз завантажується"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Установлено"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Установлено, вимкнено"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Нема з’єднання зі словником"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Словники недоступні"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Оновити"</string>
-    <string name="last_update" msgid="3101549719827600346">"Останнє оновлення"</string>
-    <string name="message_updating" msgid="820186276704134720">"Перевірка наявності оновлень"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Завантаження..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Основний словник"</string>
-    <string name="cancel" msgid="5586531736609183304">"Скасувати"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Установити"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Скасувати завантаження"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Вимкнути"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Увімкнути"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Видалити"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Доступний словник для такої мови: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Натисніть, щоб переглянути та завантажити"</string>
+    <string name="app_name" msgid="6320102637491234792">"Постачальник словника"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Постачальник словника"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Служба словника"</string>
+    <string name="download_description" msgid="6014835283119198591">"Інформація про оновлення словника"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Додаткові словники"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Словник доступний"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Налаштування для словників"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Словники користувача"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Словник користувача"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Словник доступний"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Зараз завантажується"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Установлено"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Установлено, вимкнено"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Нема з’єднання зі службою словника"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Словники недоступні"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Оновити"</string>
+    <string name="last_update" msgid="730467549913588780">"Останнє оновлення"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Перевірка наявності оновлень"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Завантаження…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Основний словник"</string>
+    <string name="cancel" msgid="6830980399865683324">"Скасувати"</string>
+    <string name="install_dict" msgid="180852772562189365">"Установити"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Скасувати"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Видалити"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Для вибраної на вашому мобільному пристрої мови доступний словник.&lt;br/&gt; Радимо &lt;b&gt;завантажити&lt;/b&gt; словник для цієї мови (<xliff:g id="LANGUAGE">%1$s</xliff:g>), щоб покращити введення тексту.&lt;br/&gt; &lt;br/&gt; У мережі 3G завантаження триває 1–2 хвилини. Якщо у вас не &lt;b&gt;безлімітний тарифний план Інтернету&lt;/b&gt;, може стягуватися плата.&lt;br/&gt; Якщо ви не впевнені щодо тарифного плану, радимо скористатися з’єднанням Wi-Fi, щоб автоматично почати завантаження.&lt;br/&gt; &lt;br/&gt; Порада: завантажувати та вилучати словники можна в меню &lt;b&gt;Налаштування&lt;/b&gt; в розділі &lt;b&gt;Мова та введення&lt;/b&gt; вашого мобільного пристрою."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Завантажити зараз (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> Mб)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Завантажити через Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Доступний словник для такої мови: <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Натисніть, щоб переглянути та завантажити"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Скоро почнеться завантаження пропозицій для такої мови: <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
 </resources>
diff --git a/java/res/values-vi/strings-appname.xml b/java/res/values-vi/strings-appname.xml
deleted file mode 100644
index 6e32d03..0000000
--- a/java/res/values-vi/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Bàn phím Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Trình kiểm tra chính tả Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Cài đặt bàn phím Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Cài đặt kiểm tra chính tả"</string>
-</resources>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 12d05bb..5670106 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Bàn phím Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Bàn phím Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Cài đặt bàn phím Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Trình kiểm tra chính tả Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Cài đặt trình kiểm tra chính tả Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Tùy chọn nhập"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Lệnh ghi nhật ký cho nghiên cứu"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Trình kiểm tra chính tả Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Tra cứu tên liên hệ"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Trình kiểm tra chính tả sử dụng các mục nhập từ danh sách liên hệ của bạn"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rung khi nhấn phím"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Nhập liệu bằng giọng nói đã bị tắt"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Định cấu hình phương thức nhập"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Ngôn ngữ nhập"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Gửi phản hồi"</string>
     <string name="select_language" msgid="3693815588777926848">"Ngôn ngữ nhập"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Chạm lại để lưu"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Có sẵn từ điển"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Bật phản hồi của người dùng"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Giúp nâng cao trình chỉnh sửa phương thức nhập này bằng cách tự động gửi thống kê sử dụng và báo cáo sự cố cho Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Chủ đề bàn phím"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Tiếng Anh (Anh)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Tiếng Anh (Mỹ)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Để sau"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Đã tồn tại kiểu nhập tương tự: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Chế độ nghiên cứu tính khả dụng"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Cài đặt thời gian chờ cho nhấn và giữ phím"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Cài đặt thời gian rung khi nhấn phím"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Cài đặt âm lượng khi nhấn phím"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Đọc tệp từ điển bên ngoài"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Không có tệp từ điển nào trong thư mục Nội dung tải xuống"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Chọn tệp từ điển để cài đặt"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Mặc định"</string>
     <string name="language_settings" msgid="1671153053201809031">"Ngôn ngữ và phương thức nhập"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Chọn phương thức nhập"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Nhà cung cấp từ điển"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Nhà cung cấp từ điển"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Dịch vụ từ điển"</string>
-    <string name="download_description" msgid="3274861514695032954">"Thông tin cập nhật từ điển"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Từ điển phụ trợ"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Có sẵn từ điển"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Cài đặt dành cho từ điển"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Từ điển người dùng"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Từ điển người dùng"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Có sẵn từ điển"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Hiện đang tải xuống"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Đã cài đặt"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Đã cài đặt, bị tắt"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Lỗi knối d.vụ t.điển"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Không có từ điển nào"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Làm mới"</string>
-    <string name="last_update" msgid="3101549719827600346">"Cập nhật lần cuối"</string>
-    <string name="message_updating" msgid="820186276704134720">"Đang kiểm tra cập nhật"</string>
-    <string name="message_loading" msgid="8611339149825047446">"Đang tải..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Từ điển chính"</string>
-    <string name="cancel" msgid="5586531736609183304">"Hủy"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Cài đặt"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Hủy tải xuống"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Tắt"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Bật"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Xóa"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Có sẵn từ điển cho <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Nhấn để xem lại và tải xuống"</string>
+    <string name="app_name" msgid="6320102637491234792">"Nhà cung cấp từ điển"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Nhà cung cấp từ điển"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Dịch vụ từ điển"</string>
+    <string name="download_description" msgid="6014835283119198591">"Thông tin cập nhật từ điển"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Từ điển bổ sung"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Từ điển có sẵn"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Cài đặt cho từ điển"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Từ điển người dùng"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Từ điển người dùng"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Từ điển có sẵn"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Hiện đang tải xuống"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Đã cài đặt"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Đã cài đặt, bị tắt"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Lỗi kết nối DV từ điển"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Không có từ điển nào"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Làm mới"</string>
+    <string name="last_update" msgid="730467549913588780">"Cập nhật lần cuối"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Đang kiểm tra cập nhật"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Đang tải..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Từ điển chính"</string>
+    <string name="cancel" msgid="6830980399865683324">"Hủy"</string>
+    <string name="install_dict" msgid="180852772562189365">"Cài đặt"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Hủy"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Xóa"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Ngôn ngữ đã chọn trên thiết bị di động của bạn hiện có từ điển.&lt;br/&gt; Bạn nên &lt;b&gt;tải xuống&lt;/b&gt; từ điển <xliff:g id="LANGUAGE">%1$s</xliff:g> để cải thiện trải nghiệm nhập của mình.&lt;br/&gt; &lt;br/&gt; Quá trình tải xuống có thể mất vài phút qua 3G. Có thể mất phí nếu bạn không có &lt;b&gt;gói dữ liệu không giới hạn&lt;/b&gt;.&lt;br/&gt; Nếu bạn không chắc mình có gói dữ liệu nào, bạn nên tìm kết nối Wi-Fi để bắt đầu tải xuống tự động.&lt;br/&gt; &lt;br/&gt; Mẹo: Bạn có thể tải xuống và xóa từ điển bằng cách đi tới &lt;b&gt;Ngôn ngữ và nhập&lt;/b&gt; trong trình đơn &lt;b&gt;Cài đặt&lt;/b&gt; trên thiết bị di động của mình."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Tải xuống bây giờ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Tải xuống qua Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Có sẵn từ điển cho <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Nhấn để xem lại và tải xuống"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Tải xuống: đề xuất đối với <xliff:g id="LANGUAGE">%1$s</xliff:g> sẽ sớm sẵn sàng."</string>
 </resources>
diff --git a/java/res/values-zh-rCN/strings-appname.xml b/java/res/values-zh-rCN/strings-appname.xml
deleted file mode 100644
index f5e12fd..0000000
--- a/java/res/values-zh-rCN/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android 键盘"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android 拼写检查工具"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android 键盘设置"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"拼写检查设置"</string>
-</resources>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 0e2fd7c..3054d13 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 键盘 (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android 键盘 (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android 键盘设置 (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android 拼写检查工具 (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android 拼写检查工具设置 (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"输入选项"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"研究记录命令"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 拼写检查工具 (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查找联系人姓名"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼写检查工具会使用您的联系人列表中的条目"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按键振动"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"语音输入功能已停用"</string>
     <string name="configure_input_method" msgid="373356270290742459">"配置输入法"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"输入语言"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"发送反馈"</string>
     <string name="select_language" msgid="3693815588777926848">"输入语言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次触摸即可保存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"有可用词典"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"启用用户反馈"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"自动向 Google 发送使用情况统计信息和崩溃报告,帮助改进该输入法编辑器。"</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"键盘主题"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英语(英国)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英语(美国)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"以后再说"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"已经存在相同的输入风格:<xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"可用性研究模式"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"按键长按延迟设置"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"按键振动持续时间设置"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"按键音量设置"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"读取外部词典文件"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"“下载内容”文件夹中没有词典文件"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"选择要安装的词典文件"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"默认"</string>
     <string name="language_settings" msgid="1671153053201809031">"语言和输入法"</string>
     <string name="select_input_method" msgid="4301602374609275003">"选择输入法"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"词典大全"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"词典大全"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"字典服务"</string>
-    <string name="download_description" msgid="3274861514695032954">"词典更新信息"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"附加词典"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"词典可供下载"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"词典设置"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"用户词典"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"用户词典"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"词典可供下载"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"目前正在下载"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"已安装"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"已安装,已停用"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"连接到词典服务时发生问题"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"没有可用的词典"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"刷新"</string>
-    <string name="last_update" msgid="3101549719827600346">"最后更新时间"</string>
-    <string name="message_updating" msgid="820186276704134720">"正在检查更新"</string>
-    <string name="message_loading" msgid="8611339149825047446">"正在加载..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"主词典"</string>
-    <string name="cancel" msgid="5586531736609183304">"取消"</string>
-    <string name="install_dict" msgid="5525005524697607865">"安装"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"取消下载"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"停用"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"启用"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"删除"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"<xliff:g id="LANGUAGE">%1$s</xliff:g>词典可供下载"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"按此通知即可查看和下载"</string>
+    <string name="app_name" msgid="6320102637491234792">"词典提供程序"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"词典提供程序"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"词典服务"</string>
+    <string name="download_description" msgid="6014835283119198591">"词典更新信息"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"附加词典"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"词典现已可下载"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"词典设置"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"用户词典"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"用户词典"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"词典现已可下载"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"目前正在下载"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"已安装"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"已安装,但目前已停用"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"连接到词典服务时发生问题"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"没有可供下载的词典"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"刷新"</string>
+    <string name="last_update" msgid="730467549913588780">"上次更新时间"</string>
+    <string name="message_updating" msgid="4457761393932375219">"正在检查更新"</string>
+    <string name="message_loading" msgid="8689096636874758814">"正在加载..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"主词典"</string>
+    <string name="cancel" msgid="6830980399865683324">"取消"</string>
+    <string name="install_dict" msgid="180852772562189365">"安装"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"取消"</string>
+    <string name="delete_dict" msgid="756853268088330054">"删除"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"支持您移动设备上所选语言的词典现已可供下载啦!&lt;br/&gt;建议您&lt;b&gt;下载&lt;/b&gt;这部<xliff:g id="LANGUAGE">%1$s</xliff:g>词典,以享受更好的输入体验。&lt;br/&gt;&lt;br/&gt;通过 3G 进行下载可能需要 1 到 2 分钟的时间。如果您使用的不是&lt;b&gt;无流量限制的套餐&lt;/b&gt;,则可能需要支付一定的费用。&lt;br/&gt;如果您不确定自己使用的是哪种流量套餐,建议您使用 Wi-Fi 连接自动开始下载。&lt;br/&gt;&lt;br/&gt;提示:您可以访问移动设备的&lt;b&gt;设置&lt;/b&gt;菜单中的&lt;b&gt;语言和输入法&lt;/b&gt;,来下载和删除词典。"</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"立即下载 (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"通过 Wi-Fi 下载"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g>词典现已可下载"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"按此通知即可查看和下载"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"下载中:很快就能启用<xliff:g id="LANGUAGE">%1$s</xliff:g>的词典建议服务了!"</string>
 </resources>
diff --git a/java/res/values-zh-rTW/strings-appname.xml b/java/res/values-zh-rTW/strings-appname.xml
deleted file mode 100644
index 8cc6638..0000000
--- a/java/res/values-zh-rTW/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Android 鍵盤"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Android 拼字檢查"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Android 鍵盤設定"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"拼字檢查設定"</string>
-</resources>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index ae4a48f..d9d4751 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 鍵盤 (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android 鍵盤 (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android 鍵盤設定 (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android 拼字檢查 (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android 拼字檢查設定 (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"研究紀錄指令"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 拼字檢查 (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查詢聯絡人姓名"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼字檢查程式使用您的聯絡人清單項目"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"語音輸入已停用"</string>
     <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"提供意見"</string>
     <string name="select_language" msgid="3693815588777926848">"輸入語言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次輕觸即可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"啟用使用者意見回饋"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"自動將使用統計資料和當機報告傳送給 Google,協助改善這個輸入法編輯器。"</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英式)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美式)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"暫時不要"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"已存在相同的輸入樣式:<xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"使用習慣學習模式"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"按鍵長按延遲設定"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"按鍵震動持續時間設定"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"按鍵音量設定"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"讀取外部字典檔案"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"「下載」資料夾中沒有任何字典檔案"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"選取要安裝的字典檔案"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"預設"</string>
     <string name="language_settings" msgid="1671153053201809031">"語言與輸入設定"</string>
     <string name="select_input_method" msgid="4301602374609275003">"選擇輸入法"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"字典提供者"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"字典提供者"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"字典服務"</string>
-    <string name="download_description" msgid="3274861514695032954">"字典更新資訊"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"外掛字典"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"字典可供下載"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"字典設定"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"使用者字典"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"使用者字典"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"可用的字典"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"目前正在下載"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"已安裝"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"已安裝但目前停用"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"連線至字典服務時發生問題"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"沒有可用的字典"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"重新整理"</string>
-    <string name="last_update" msgid="3101549719827600346">"上次更新時間"</string>
-    <string name="message_updating" msgid="820186276704134720">"正在檢查更新"</string>
-    <string name="message_loading" msgid="8611339149825047446">"載入中..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"主要字典"</string>
-    <string name="cancel" msgid="5586531736609183304">"取消"</string>
-    <string name="install_dict" msgid="5525005524697607865">"安裝"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"取消下載"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"停用"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"啟用"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"刪除"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"支援「<xliff:g id="LANGUAGE">%1$s</xliff:g>」字典"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"按下即可查看並下載"</string>
+    <string name="app_name" msgid="6320102637491234792">"字典提供者"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"字典提供者"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"字典服務"</string>
+    <string name="download_description" msgid="6014835283119198591">"字典更新資訊"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"外掛字典"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"可用的字典"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"字典設定"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"使用者字典"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"使用者字典"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"可用的字典"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"正在下載"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"已安裝"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"已安裝但目前停用"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"連線至字典服務時發生問題"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"沒有可用的字典"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"重新整理"</string>
+    <string name="last_update" msgid="730467549913588780">"上次更新時間:"</string>
+    <string name="message_updating" msgid="4457761393932375219">"正在檢查更新"</string>
+    <string name="message_loading" msgid="8689096636874758814">"載入中..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"主要字典"</string>
+    <string name="cancel" msgid="6830980399865683324">"取消"</string>
+    <string name="install_dict" msgid="180852772562189365">"安裝"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"取消"</string>
+    <string name="delete_dict" msgid="756853268088330054">"刪除"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"您的行動裝置設定的語言,現有字典可供使用。&lt;br/&gt; 建議您&lt;b&gt;下載&lt;/b&gt;<xliff:g id="LANGUAGE">%1$s</xliff:g>字典,加強輸入功能。&lt;br/&gt; &lt;br/&gt; 透過 3G 網路下載約需一兩分鐘。若無&lt;b&gt;無限行動上網資費方案&lt;/b&gt;,可能必須另外付費。&lt;br/&gt;若不確定行動上網資費方案為何,可以等連上 Wi-Fi 網路後再自動下載。&lt;br/&gt; &lt;br/&gt;提示:進入行動裝置的 [設定] 選單,選擇 [語言和輸入] 即可下載及移除字典。&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;"</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"立即下載 (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"透過 Wi-Fi 下載"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"支援<xliff:g id="LANGUAGE">%1$s</xliff:g>字典"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"按下即可查看並下載"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"下載中:即將啟用<xliff:g id="LANGUAGE">%1$s</xliff:g>字詞建議服務。"</string>
 </resources>
diff --git a/java/res/values-zu/strings-appname.xml b/java/res/values-zu/strings-appname.xml
deleted file mode 100644
index a0fb517..0000000
--- a/java/res/values-zu/strings-appname.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="178705338187710493">"Ikhibhodi ye-Android"</string>
-    <string name="spell_checker_service_name" msgid="6268342166872202903">"Isihloli sokupela se-Android"</string>
-    <string name="english_ime_settings" msgid="7470027018752707691">"Izilungiselelo zekhibhodi ye-Android"</string>
-    <string name="android_spell_checker_settings" msgid="8397842018475560441">"Izilungiselelo zokuhlola ukupela"</string>
-</resources>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 9e11821..93c8d92 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -20,10 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Ikhibhodi ye-Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Ikhibhodi ye-Android (AOSP)"</string>
+    <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Izilungiselelo zekhibhodi ye-Android (AOSP)"</string>
+    <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Isihloli sokupela se-Android (AOSP)"</string>
+    <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Izilungiselelo zesihloli sokupela se-Android (AOSP)"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Okukhethwa kukho kokungenayo"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Imiyalo yefayela lokungena lokucwaninga"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Isihloli sokupela se-Android (AOSP)"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Bheka amagama woxhumana nabo"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Isihloli sokupela sisebenzisa okungenayo kusuka kuhlu lalabo oxhumana nabo"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Dlidlizelisa ngokucindezela inkinobho"</string>
@@ -128,11 +130,13 @@
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Okufakwayo ngezwi kuvinjelwe"</string>
     <string name="configure_input_method" msgid="373356270290742459">"Misa izindlela zokufakwayo"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Izilimi zokufakwayo"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Thumela impendulo"</string>
     <string name="select_language" msgid="3693815588777926848">"Izilimi zokufakwayo"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Thinta futhi ukuze ulondoloze"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Isichazamazwi siyatholakala"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Vumela impendulo yomsebenzisi"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Siza ukuthuthukisa lo mhleli wendlela yokufakwa ngokusithumela ngokuzenzakalela izibalo zokusetshenziswa nokukhubeka ku-Google."</string>
+    <!-- no translation found for prefs_description_log (7525225584555429211) -->
+    <skip />
     <string name="keyboard_layout" msgid="8451164783510487501">"Indikimba yekhibhodi"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"i-English(UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"i-English (US)"</string>
@@ -159,9 +163,12 @@
     <string name="not_now" msgid="6172462888202790482">"Hhayi manje"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Isitayela sokufaka esifanayo sesivele sikhona: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Imodi yesitadi yokusebenziseka"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="1881822418815012326">"Izilungiselelo zokulibazisa ukucindezelwa ukhiye isikhathi eside"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Izilungiselelo ze-keypress vibration duraton"</string>
-    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Izilungiselelo zevolumu yomsindo wekeypress"</string>
+    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
+    <skip />
+    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
+    <skip />
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Funda ifayela elangaphandle lesichazamazwi"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Awekho amafayela wesichazamazwi kufolda yokulandiwe"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Khetha ifayela lesichazamazwi ukuze ulifake"</string>
@@ -170,39 +177,34 @@
     <string name="button_default" msgid="3988017840431881491">"Okuzenzakalelayo"</string>
     <string name="language_settings" msgid="1671153053201809031">"Ulimi nokokufakwayo"</string>
     <string name="select_input_method" msgid="4301602374609275003">"Khetha indlela yokufaka"</string>
-
-    <string name="app_name" msgid="1017058186322714405">"Umhlinzeki Wesichazamazwi"</string>
-    <string name="dictionary_provider_name" msgid="7710415599371161092">"Umhlinzeki Wesichazamazwi"</string>
-    <string name="dictionary_service_name" msgid="551650697348202056">"Insiza yesichazamazwi"</string>
-    <string name="download_description" msgid="3274861514695032954">"Ulwazi lokubuyekeza isichazamazwi"</string>
-    <string name="dictionary_settings_title" msgid="7243930967845020407">"Faka izichazamazwi"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3642634623465349716">"Isichazamazwi siyatholakala"</string>
-    <string name="dictionary_settings_summary" msgid="8599679434799749053">"Izilungiselelo zezichazamazwi"</string>
-    <string name="user_dictionaries" msgid="7519736232423929124">"Sebenzisa isichazamazwi"</string>
-    <string name="default_user_dict_pref_name" msgid="522125152757607790">"Isichazamazwi Somsebenzisi"</string>
-    <string name="dictionary_available" msgid="3192920608520618083">"Isichazamazwi siyatholakala"</string>
-    <string name="dictionary_downloading" msgid="859497476266309596">"Okwamanje iyalayisha"</string>
-    <string name="dictionary_installed" msgid="6425586899671378160">"Kufakiwe"</string>
-    <string name="dictionary_disabled" msgid="3448571280490746032">"Kufakiwe, kumisiwe"</string>
-    <string name="cannot_connect_to_dict_service" msgid="6875665494726300427">"Inkinga yokuxhumaniseka esevisini yesichazamazwi"</string>
-    <string name="no_dictionaries_available" msgid="5206225077945637810">"Azikho izachazimazwi ezikhona"</string>
-    <string name="check_for_updates_now" msgid="642057986127624986">"Vuselela"</string>
-    <string name="last_update" msgid="3101549719827600346">"Igcine ukulungiswa:"</string>
-    <string name="message_updating" msgid="820186276704134720">"Ihlola izibuyekezo..."</string>
-    <string name="message_loading" msgid="8611339149825047446">"Kuyalayisha..."</string>
-    <string name="main_dict_description" msgid="1679964306980098570">"Isichazimazwi sakho ngqangi"</string>
-    <string name="cancel" msgid="5586531736609183304">"Khansela"</string>
-    <string name="install_dict" msgid="5525005524697607865">"Faka"</string>
-    <string name="cancel_download_dict" msgid="7163173650298838367">"Khansela ukulayisha"</string>
-    <string name="disable_dict" msgid="7685810040236497700">"Yenza kungasebenzi"</string>
-    <string name="enable_dict" msgid="3848179784702473680">"Vumela"</string>
-    <string name="delete_dict" msgid="5817159290503843766">"Susa"</string>
-    <!-- no translation found for should_download_over_metered_prompt (4965264849057656521) -->
-    <skip />
-    <!-- no translation found for download_over_metered (4024013764937850061) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (6963770885033765378) -->
-    <skip />
-    <string name="dict_available_notification_title" msgid="4560576379680660047">"Isichazamazwi se-<xliff:g id="LANGUAGE">%1$s</xliff:g> siyatholakala"</string>
-    <string name="dict_available_notification_description" msgid="355515381285317832">"Cindezela ukuze ubuyekeze bese ulanda"</string>
+    <string name="app_name" msgid="6320102637491234792">"Umhlinzeki wesichazamazwi"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Umhlinzeki wesichazamazwi"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Isevisi yesichazamazwi"</string>
+    <string name="download_description" msgid="6014835283119198591">"Ulwazi lokubuyekeza isichazamazwi"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Izichazamazwi ezingezwayo"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Isichazamazwi siyatholakala"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Izilungiselelo zezichazamazwi"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Izichazamazwi zomsebenzisi"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Isichazamazwi somsebenzisi"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Isichazamazwi siyatholakala"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Okwamanje iyalanda"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Kufakiwe"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Kufakiwe, kukhutshaziwe"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Inkinga yokuxhumanisa kusevisi yesichazamazwi"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Azikho izachazimazwi ezitholakalayo"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Qala kabusha"</string>
+    <string name="last_update" msgid="730467549913588780">"Igcine ukulungiswa"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Ihlola izibuyekezo"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Iyalayisha..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Isichazamazwi sakho esisemqoka"</string>
+    <string name="cancel" msgid="6830980399865683324">"Khansela"</string>
+    <string name="install_dict" msgid="180852772562189365">"Faka"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Khansela"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Susa"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Ulimi olukhethiwe kudivayisi yakho yeselula linesichazamazwi esitholakalayo.&lt;br/&gt; Sincoma &lt;b&gt;ukulanda&lt;/b&gt; isichazamazwi sesi-<xliff:g id="LANGUAGE">%1$s</xliff:g> ukwenza kangcono isipiliyoni sakho sokuthayipha.&lt;br/&gt; &lt;br/&gt; Ukulanda ukungathatha iminithi noma amaminithi amabili nge-3G. Amashaja angasebenza uma ungenalo &lt;b&gt;icebo ledatha elinganqunyelwe&lt;/b&gt;.&lt;br/&gt; Uma ungenasiqinisekiso sokuthi iliphi icebo ledatha onalo, sincoma ukuthola uxhumo lwe-Wi-Fi ukuze uqale ukulanda ngokuzenzakalelayo.&lt;br/&gt; &lt;br/&gt; Ithiphu: Ungalanda futhi ususe izichazamazwi ngokuya ku-&lt;b&gt;Ulimi nokungenayo&lt;/b&gt; kumenyu ye-&lt;b&gt;Izilungiselelo&lt;/b&gt; yedivayisi yakho yeselula."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Landa manje (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Landa nge-Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"Isichazamazwi se-<xliff:g id="LANGUAGE">%1$s</xliff:g> siyatholakala"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Cindezela ukuze ubuyekeze uphinde ulande"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Ukulanda: iziphakamiso ze-<xliff:g id="LANGUAGE">%1$s</xliff:g> zizolunga maduze."</string>
 </resources>
diff --git a/java/res/values/strings-appname.xml b/java/res/values/strings-appname.xml
deleted file mode 100644
index 19aaa25..0000000
--- a/java/res/values/strings-appname.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources>
-    <!-- Title for Latin Keyboard  -->
-    <string name="english_ime_name">Android keyboard</string>
-
-    <!-- Name of Android spell checker service -->
-    <string name="spell_checker_service_name">Android spell checker</string>
-
-    <!-- Title for Latin keyboard settings activity / dialog -->
-    <string name="english_ime_settings">Android keyboard settings</string>
-
-    <!-- Title for the spell checking service settings screen -->
-    <string name="android_spell_checker_settings">Spell checking settings</string>
-</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 2735251..201fc70 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -19,14 +19,22 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Application name for opensource Android keyboard. AOSP(Android Open Source Project) should not be translated. -->
-    <string name="aosp_android_keyboard_ime_name">Android keyboard (AOSP)</string>
-    <!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] -->
-    <string name="english_ime_input_options">Input options</string>
-    <!-- Title for Latin keyboard research log dialog, which contains special commands for users that contribute data for research. [CHAR LIMIT=33] -->
-    <string name="english_ime_research_log">Research Log Commands</string>
+    <string name="aosp_android_keyboard_ime_name">Android Keyboard (AOSP)</string>
+
+    <!-- Title for Android Keyboard settings screen. AOSP(Android Open Source Project) should not be translated. -->
+    <string name="aosp_android_keyboard_ime_settings">Android Keyboard Settings (AOSP)</string>
 
     <!-- Name of Android spell checker service. AOSP(Android Open Source Project) should not be translated. -->
-    <string name="aosp_spell_checker_service_name">Android spell checker (AOSP)</string>
+    <string name="aosp_spell_checker_service_name">Android Spell Checker (AOSP)</string>
+
+    <!-- Title for the spell checking service settings screen. AOSP(Android Open Source Project) should not be translated. -->
+    <string name="aosp_android_spell_checker_service_settings">Android Spell Checker Settings (AOSP)</string>
+
+    <!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] -->
+    <string name="english_ime_input_options">Input options</string>
+
+    <!-- Title for Latin keyboard research log dialog, which contains special commands for users that contribute data for research. [CHAR LIMIT=33] -->
+    <string name="english_ime_research_log">Research Log Commands</string>
 
     <!-- Title for the spell checker option to turn on/off contact names lookup [CHAR LIMIT=25] -->
     <string name="use_contacts_for_spellchecking_option_title">Look up contact names</string>
@@ -342,10 +350,10 @@
     <!-- Inform the user that a particular language has an available dictionary -->
     <string name="has_dictionary">Dictionary available</string>
 
-    <!-- Preferences item for enabling to send user statistics to Google -->
+    <!-- Preferences item for enabling to send user statistics for development only diagnostics -->
     <string name="prefs_enable_log">Enable user feedback</string>
-    <!-- Description for enabling to send user statistics to Google -->
-    <string name="prefs_description_log">Help improve this input method editor by automatically sending usage statistics and crash reports to Google.</string>
+    <!-- Description for enabling to send user statistics for development only diagnostics -->
+    <string name="prefs_description_log">Help improve this input method editor by automatically sending usage statistics and crash reports</string>
 
     <!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]-->
     <string name="keyboard_layout">Keyboard theme</string>
@@ -414,12 +422,12 @@
 
     <!-- Title of an option for usability study mode -->
     <string name="prefs_usability_study_mode">Usability study mode</string>
-    <!-- Title of the settings for key long press delay -->
-    <string name="prefs_key_longpress_timeout_settings">Key long press delay settings</string>
-    <!-- Title of the settings for keypress vibration duration -->
-    <string name="prefs_keypress_vibration_duration_settings">Keypress vibration duration settings</string>
-    <!-- Title of the settings for keypress sound volume -->
-    <string name="prefs_keypress_sound_volume_settings">Keypress sound volume settings</string>
+    <!-- Title of the settings for key long press delay [CHAR LIMIT=30] -->
+    <string name="prefs_key_longpress_timeout_settings">Key long press delay</string>
+    <!-- Title of the settings for keypress vibration duration [CHAR LIMIT=30] -->
+    <string name="prefs_keypress_vibration_duration_settings">Keypress vibration duration</string>
+    <!-- Title of the settings for keypress sound volume [CHAR LIMIT=30] -->
+    <string name="prefs_keypress_sound_volume_settings">Keypress sound volume</string>
     <!-- Title of the settings for reading an external dictionary file -->
     <string name="prefs_read_external_dictionary">Read external dictionary file</string>
     <!-- Message to show when there are no files to install as an external dictionary [CHAR LIMIT=100] -->
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index e299ce4..7839462 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -17,7 +17,6 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
-    android:title="@string/english_ime_settings"
     android:key="english_ime_settings">
     <PreferenceCategory
         android:title="@string/general_category"
diff --git a/java/res/xml/spell_checker_settings.xml b/java/res/xml/spell_checker_settings.xml
index 222b98b..de67e7f 100644
--- a/java/res/xml/spell_checker_settings.xml
+++ b/java/res/xml/spell_checker_settings.xml
@@ -15,8 +15,7 @@
 -->
 
 <PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:title="@string/android_spell_checker_settings">
+    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"
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index c0028e4..73896df 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -64,6 +64,9 @@
      */
     private int mEdgeSlop;
 
+    /** The most recently set keyboard mode. */
+    private int mLastKeyboardMode;
+
     public static void init(final InputMethodService inputMethod) {
         sInstance.initInternal(inputMethod);
     }
@@ -113,16 +116,19 @@
         if (mView == null) {
             return;
         }
-
         if (mAccessibilityNodeProvider != null) {
             mAccessibilityNodeProvider.setKeyboard();
         }
+        final int keyboardMode = mView.getKeyboard().mId.mMode;
 
         // Since this method is called even when accessibility is off, make sure
-        // to check the state before announcing anything.
-        if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
-            announceKeyboardMode();
+        // to check the state before announcing anything. Also, don't announce
+        // changes within the same mode.
+        if (AccessibilityUtils.getInstance().isAccessibilityEnabled()
+                && (mLastKeyboardMode != keyboardMode)) {
+            announceKeyboardMode(keyboardMode);
         }
+        mLastKeyboardMode = keyboardMode;
     }
 
     /**
@@ -132,25 +138,24 @@
         if (mView == null) {
             return;
         }
-
         announceKeyboardHidden();
+        mLastKeyboardMode = -1;
     }
 
     /**
      * Announces which type of keyboard is being displayed. If the keyboard type
      * is unknown, no announcement is made.
+     *
+     * @param mode The new keyboard mode.
      */
-    private void announceKeyboardMode() {
-        final Keyboard keyboard = mView.getKeyboard();
-        final int resId = KEYBOARD_MODE_RES_IDS.get(keyboard.mId.mMode);
+    private void announceKeyboardMode(int mode) {
+        final int resId = KEYBOARD_MODE_RES_IDS.get(mode);
         if (resId == 0) {
             return;
         }
-
         final Context context = mView.getContext();
         final String keyboardMode = context.getString(resId);
         final String text = context.getString(R.string.announce_keyboard_mode, keyboardMode);
-
         sendWindowStateChanged(text);
     }
 
@@ -167,7 +172,7 @@
     /**
      * Sends a window state change event with the specified text.
      *
-     * @param text
+     * @param text The text to send with the event.
      */
     private void sendWindowStateChanged(final String text) {
         final AccessibilityEvent stateChange = AccessibilityEvent.obtain(
@@ -195,7 +200,6 @@
         if (mView == null) {
             return null;
         }
-
         return getAccessibilityNodeProvider();
     }
 
@@ -248,11 +252,9 @@
         case MotionEvent.ACTION_HOVER_MOVE:
             if (key != previousKey) {
                 return onTransitionKey(key, previousKey, event);
-            } else {
-                return onHoverKey(key, event);
             }
+            return onHoverKey(key, event);
         }
-
         return false;
     }
 
@@ -294,18 +296,13 @@
     private boolean onTransitionKey(final Key currentKey, final Key previousKey,
             final MotionEvent event) {
         final int savedAction = event.getAction();
-
         event.setAction(MotionEvent.ACTION_HOVER_EXIT);
         onHoverKey(previousKey, event);
-
         event.setAction(MotionEvent.ACTION_HOVER_ENTER);
         onHoverKey(currentKey, event);
-
         event.setAction(MotionEvent.ACTION_HOVER_MOVE);
         final boolean handled = onHoverKey(currentKey, event);
-
         event.setAction(savedAction);
-
         return handled;
     }
 
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
index 0c8b466..6961588 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
@@ -25,16 +25,34 @@
  */
 public class DictionaryPackConstants {
     /**
+     * The root domain for the dictionary pack, upon which authorities and actions will append
+     * their own distinctive strings.
+     */
+    private static final String DICTIONARY_DOMAIN = "com.android.inputmethod.dictionarypack";
+
+    /**
      * Authority for the ContentProvider protocol.
      */
     // TODO: find some way to factorize this string with the one in the resources
-    public static final String AUTHORITY = "com.android.inputmethod.dictionarypack.aosp";
+    public static final String AUTHORITY = DICTIONARY_DOMAIN + ".aosp";
 
     /**
      * The action of the intent for publishing that new dictionary data is available.
      */
     // TODO: make this different across different packages. A suggested course of action is
     // to use the package name inside this string.
-    public static final String NEW_DICTIONARY_INTENT_ACTION =
-            "com.android.inputmethod.dictionarypack.newdict";
+    // NOTE: The appended string should be uppercase like all other actions, but it's not for
+    // historical reasons.
+    public static final String NEW_DICTIONARY_INTENT_ACTION = DICTIONARY_DOMAIN + ".newdict";
+
+    /**
+     * The action of the intent sent by the dictionary pack to ask for a client to make
+     * itself known. This is used when the settings activity is brought up for a client the
+     * dictionary pack does not know about.
+     */
+    public static final String UNKNOWN_DICTIONARY_PROVIDER_CLIENT = DICTIONARY_DOMAIN
+            + ".UNKNOWN_CLIENT";
+    // In the above intents, the name of the string extra that contains the name of the client
+    // we want information about.
+    public static final String DICTIONARY_PROVIDER_CLIENT_EXTRA = "client";
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
index 77b3b8e..f8d1c4f 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
@@ -509,6 +509,11 @@
                 } catch (final BadFormatException e) {
                     Log.w(TAG, "Not enough information to insert this dictionary " + values, e);
                 }
+                // We just received new information about the list of dictionary for this client.
+                // For all intents and purposes, this is new metadata, so we should publish it
+                // so that any listeners (like the Settings interface for example) can update
+                // themselves.
+                UpdateHandler.publishUpdateMetadataCompleted(getContext(), true);
                 break;
             case DICTIONARY_V1_WHOLE_LIST:
             case DICTIONARY_V1_DICT_INFO:
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index 7e2a6bb..9e27c1f 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -110,6 +110,15 @@
         super.onResume();
         mChangedSettings = false;
         UpdateHandler.registerUpdateEventListener(this);
+        final Activity activity = getActivity();
+        if (!MetadataDbHelper.isClientKnown(activity, mClientId)) {
+            Log.i(TAG, "Unknown dictionary pack client: " + mClientId + ". Requesting info.");
+            final Intent unknownClientBroadcast =
+                    new Intent(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT);
+            unknownClientBroadcast.putExtra(
+                    DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA, mClientId);
+            activity.sendBroadcast(unknownClientBroadcast);
+        }
         final IntentFilter filter = new IntentFilter();
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         getActivity().registerReceiver(mConnectivityChangedReceiver, filter);
@@ -130,6 +139,7 @@
         }
     }
 
+    @Override
     public void downloadedMetadata(final boolean succeeded) {
         stopLoadingAnimation();
         if (!succeeded) return; // If the download failed nothing changed, so no need to refresh
@@ -141,6 +151,7 @@
         }.start();
     }
 
+    @Override
     public void wordListDownloadFinished(final String wordListId, final boolean succeeded) {
         final WordListPreference pref = findWordListPreference(wordListId);
         if (null == pref) return;
@@ -177,6 +188,7 @@
         return null;
     }
 
+    @Override
     public void updateCycleCompleted() {}
 
     private void refreshNetworkState() {
@@ -260,6 +272,7 @@
         } else if (!cursor.moveToFirst()) {
             final ArrayList<Preference> result = new ArrayList<Preference>();
             result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
+            cursor.close();
             return result;
         } else {
             final String systemLocaleString = Locale.getDefault().toString();
@@ -289,6 +302,7 @@
                     prefList.put(key, pref);
                 }
             } while (cursor.moveToNext());
+            cursor.close();
             return prefList.values();
         }
     }
@@ -335,8 +349,7 @@
     private void cancelRefresh() {
         UpdateHandler.unregisterUpdateEventListener(this);
         final Context context = getActivity();
-        UpdateHandler.cancelUpdate(context,
-                MetadataDbHelper.getMetadataUriAsString(context, mClientId));
+        UpdateHandler.cancelUpdate(context, mClientId);
         stopLoadingAnimation();
     }
 
@@ -359,7 +372,12 @@
                             getActivity(), android.R.anim.fade_out));
                     preferenceView.startAnimation(AnimationUtils.loadAnimation(
                             getActivity(), android.R.anim.fade_in));
-                    mUpdateNowMenu.setTitle(R.string.check_for_updates_now);
+                    // The menu is created by the framework asynchronously after the activity,
+                    // which means it's possible to have the activity running but the menu not
+                    // created yet - hence the necessity for a null check here.
+                    if (null != mUpdateNowMenu) {
+                        mUpdateNowMenu.setTitle(R.string.check_for_updates_now);
+                    }
                 }
             });
     }
diff --git a/java/src/com/android/inputmethod/dictionarypack/EventHandler.java b/java/src/com/android/inputmethod/dictionarypack/EventHandler.java
index 96c4a83..d8aa33b 100644
--- a/java/src/com/android/inputmethod/dictionarypack/EventHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/EventHandler.java
@@ -16,13 +16,9 @@
 
 package com.android.inputmethod.dictionarypack;
 
-import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.R;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.util.Log;
 
 public final class EventHandler extends BroadcastReceiver {
     private static final String TAG = EventHandler.class.getName();
diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
index b472750..e05a79b 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -444,7 +444,19 @@
         manager.remove(fileId);
     }
 
-    private static void publishUpdateMetadataCompleted(final Context context,
+    /**
+     * Sends a broadcast informing listeners that the dictionaries were updated.
+     *
+     * This will call all local listeners through the UpdateEventListener#downloadedMetadata
+     * callback (for example, the dictionary provider interface uses this to stop the Loading
+     * animation) and send a broadcast about the metadata having been updated. For a client of
+     * the dictionary pack like Latin IME, this means it should re-query the dictionary pack
+     * for any relevant new data.
+     *
+     * @param context the context, to send the broadcast.
+     * @param downloadSuccessful whether the download of the metadata was successful or not.
+     */
+    public static void publishUpdateMetadataCompleted(final Context context,
             final boolean downloadSuccessful) {
         // We need to warn all listeners of what happened. But some listeners may want to
         // remove themselves or re-register something in response. Hence we should take a
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index fd9edec..5e68c70 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -301,8 +301,10 @@
             final int xmlId = mResources.getIdentifier(keyboardLayoutSetName, "xml", packageName);
             try {
                 parseKeyboardLayoutSet(mResources, xmlId);
-            } catch (Exception e) {
-                throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName);
+            } catch (final IOException e) {
+                throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName, e);
+            } catch (final XmlPullParserException e) {
+                throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName, e);
             }
             return new KeyboardLayoutSet(mContext, mParams);
         }
@@ -311,14 +313,14 @@
                 throws XmlPullParserException, IOException {
             final XmlResourceParser parser = res.getXml(resId);
             try {
-                int event;
-                while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                    final int event = parser.next();
                     if (event == XmlPullParser.START_TAG) {
                         final String tag = parser.getName();
                         if (TAG_KEYBOARD_SET.equals(tag)) {
                             parseKeyboardLayoutSetContent(parser);
                         } else {
-                            throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+                            throw new XmlParseUtils.IllegalStartTag(parser, tag, TAG_KEYBOARD_SET);
                         }
                     }
                 }
@@ -329,21 +331,21 @@
 
         private void parseKeyboardLayoutSetContent(final XmlPullParser parser)
                 throws XmlPullParserException, IOException {
-            int event;
-            while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                final int event = parser.next();
                 if (event == XmlPullParser.START_TAG) {
                     final String tag = parser.getName();
                     if (TAG_ELEMENT.equals(tag)) {
                         parseKeyboardLayoutSetElement(parser);
                     } else {
-                        throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+                        throw new XmlParseUtils.IllegalStartTag(parser, tag, TAG_KEYBOARD_SET);
                     }
                 } else if (event == XmlPullParser.END_TAG) {
                     final String tag = parser.getName();
                     if (TAG_KEYBOARD_SET.equals(tag)) {
                         break;
                     } else {
-                        throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEYBOARD_SET);
+                        throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET);
                     }
                 }
             }
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index f0ca9c1..745e7df 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -229,6 +229,9 @@
         @Override
         public void handleMessage(final Message msg) {
             final MainKeyboardView keyboardView = getOuterInstance();
+            if (keyboardView == null) {
+                return;
+            }
             final PointerTracker tracker = (PointerTracker) msg.obj;
             switch (msg.what) {
             case MSG_TYPING_STATE_EXPIRED:
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
index b047fe0..e3e6d39 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
@@ -44,6 +44,7 @@
     // The wall time of the zero value in {@link #mEventTimes}
     private long mCurrentTimeBase;
     private int mTrailStartIndex;
+    private int mLastInterpolatedDrawIndex;
 
     static final class Params {
         public final int mTrailColor;
@@ -96,6 +97,17 @@
         }
         final int[] eventTimes = mEventTimes.getPrimitiveArray();
         final int strokeId = stroke.getGestureStrokeId();
+        // Because interpolation algorithm in {@link GestureStrokeWithPreviewPoints} can't determine
+        // the interpolated points in the last segment of gesture stroke, it may need recalculation
+        // of interpolation when new segments are added to the stroke.
+        // {@link #mLastInterpolatedDrawIndex} holds the start index of the last segment. It may
+        // be updated by the interpolation
+        // {@link GestureStrokeWithPreviewPoints#interpolatePreviewStroke}
+        // or by animation {@link #drawGestureTrail(Canvas,Paint,Rect,Params)} below.
+        final int lastInterpolatedIndex = (strokeId == mCurrentStrokeId)
+                ? mLastInterpolatedDrawIndex : trailSize;
+        mLastInterpolatedDrawIndex = stroke.interpolateStrokeAndReturnStartIndexOfLastSegment(
+                lastInterpolatedIndex, mEventTimes, mXCoordinates, mYCoordinates);
         if (strokeId != mCurrentStrokeId) {
             final int elapsedTime = (int)(downTime - mCurrentTimeBase);
             for (int i = mTrailStartIndex; i < trailSize; i++) {
@@ -216,6 +228,10 @@
                 System.arraycopy(eventTimes, startIndex, eventTimes, 0, newSize);
                 System.arraycopy(xCoords, startIndex, xCoords, 0, newSize);
                 System.arraycopy(yCoords, startIndex, yCoords, 0, newSize);
+                // The start index of the last segment of the stroke
+                // {@link mLastInterpolatedDrawIndex} should also be updated because all array
+                // elements have just been shifted for compaction.
+                mLastInterpolatedDrawIndex = Math.max(mLastInterpolatedDrawIndex - startIndex, 0);
             }
             mEventTimes.setLength(newSize);
             mXCoordinates.setLength(newSize);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
index fc81410..3315954 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
@@ -21,19 +21,32 @@
 public final class GestureStrokeWithPreviewPoints extends GestureStroke {
     public static final int PREVIEW_CAPACITY = 256;
 
+    private static final boolean ENABLE_INTERPOLATION = true;
+
     private final ResizableIntArray mPreviewEventTimes = new ResizableIntArray(PREVIEW_CAPACITY);
     private final ResizableIntArray mPreviewXCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
     private final ResizableIntArray mPreviewYCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
 
     private int mStrokeId;
     private int mLastPreviewSize;
+    private final HermiteInterpolator mInterpolator = new HermiteInterpolator();
+    private int mLastInterpolatedPreviewIndex;
 
-    private int mMinPreviewSampleLengthSquare;
+    private int mMinPreviewSamplingDistanceSquared;
     private int mLastX;
     private int mLastY;
+    private double mMinPreviewSamplingDistance;
+    private double mDistanceFromLastSample;
 
-    // TODO: Move this to resource.
-    private static final float MIN_PREVIEW_SAMPLE_LENGTH_RATIO_TO_KEY_WIDTH = 0.1f;
+    // TODO: Move these constants to resource.
+    // The minimum linear distance between sample points for preview in keyWidth unit.
+    private static final float MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH = 0.1f;
+    // The minimum trail distance between sample points for preview in keyWidth unit when using
+    // interpolation.
+    private static final float MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH_WITH_INTERPOLATION = 0.2f;
+    // The angular threshold to use interpolation in radian. PI/12 is 15 degree.
+    private static final double INTERPOLATION_ANGULAR_THRESHOLD = Math.PI / 12.0d;
+    private static final int MAX_INTERPOLATION_PARTITION = 4;
 
     public GestureStrokeWithPreviewPoints(final int pointerId, final GestureStrokeParams params) {
         super(pointerId, params);
@@ -44,6 +57,7 @@
         super.reset();
         mStrokeId++;
         mLastPreviewSize = 0;
+        mLastInterpolatedPreviewIndex = 0;
         mPreviewEventTimes.setLength(0);
         mPreviewXCoordinates.setLength(0);
         mPreviewYCoordinates.setLength(0);
@@ -53,35 +67,49 @@
         return mStrokeId;
     }
 
-    public int getGestureStrokePreviewSize() {
-        return mPreviewEventTimes.getLength();
-    }
-
     @Override
     public void setKeyboardGeometry(final int keyWidth, final int keyboardHeight) {
         super.setKeyboardGeometry(keyWidth, keyboardHeight);
-        final float sampleLength = keyWidth * MIN_PREVIEW_SAMPLE_LENGTH_RATIO_TO_KEY_WIDTH;
-        mMinPreviewSampleLengthSquare = (int)(sampleLength * sampleLength);
+        final float samplingRatioToKeyWidth = ENABLE_INTERPOLATION
+                ? MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH_WITH_INTERPOLATION
+                : MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH;
+        mMinPreviewSamplingDistance = keyWidth * samplingRatioToKeyWidth;
+        mMinPreviewSamplingDistanceSquared = (int)(
+                mMinPreviewSamplingDistance * mMinPreviewSamplingDistance);
     }
 
-    private boolean needsSampling(final int x, final int y) {
+    private boolean needsSampling(final int x, final int y, final boolean isMajorEvent) {
+        if (ENABLE_INTERPOLATION) {
+            mDistanceFromLastSample += Math.hypot(x - mLastX, y - mLastY);
+            mLastX = x;
+            mLastY = y;
+            if (mDistanceFromLastSample >= mMinPreviewSamplingDistance) {
+                mDistanceFromLastSample = 0.0d;
+                return true;
+            }
+            return false;
+        }
+
         final int dx = x - mLastX;
         final int dy = y - mLastY;
-        return dx * dx + dy * dy >= mMinPreviewSampleLengthSquare;
+        if (isMajorEvent || dx * dx + dy * dy >= mMinPreviewSamplingDistanceSquared) {
+            mLastX = x;
+            mLastY = y;
+            return true;
+        }
+        return false;
     }
 
     @Override
     public boolean addPointOnKeyboard(final int x, final int y, final int time,
             final boolean isMajorEvent) {
-        final boolean onValidArea = super.addPointOnKeyboard(x, y, time, isMajorEvent);
-        if (isMajorEvent || needsSampling(x, y)) {
+        if (needsSampling(x, y, isMajorEvent)) {
             mPreviewEventTimes.add(time);
             mPreviewXCoordinates.add(x);
             mPreviewYCoordinates.add(y);
-            mLastX = x;
-            mLastY = y;
         }
-        return onValidArea;
+        return super.addPointOnKeyboard(x, y, time, isMajorEvent);
+
     }
 
     public void appendPreviewStroke(final ResizableIntArray eventTimes,
@@ -95,4 +123,82 @@
         yCoords.append(mPreviewYCoordinates, mLastPreviewSize, length);
         mLastPreviewSize = mPreviewEventTimes.getLength();
     }
+
+    /**
+     * Calculate interpolated points between the last interpolated point and the end of the trail.
+     * And return the start index of the last interpolated segment of input arrays because it
+     * may need to recalculate the interpolated points in the segment if further segments are
+     * added to this stroke.
+     *
+     * @param lastInterpolatedIndex the start index of the last interpolated segment of
+     *        <code>eventTimes</code>, <code>xCoords</code>, and <code>yCoords</code>.
+     * @param eventTimes the event time array of gesture preview trail to be drawn.
+     * @param xCoords the x-coordinates array of gesture preview trail to be drawn.
+     * @param yCoords the y-coordinates array of gesture preview trail to be drawn.
+     * @return the start index of the last interpolated segment of input arrays.
+     */
+    public int interpolateStrokeAndReturnStartIndexOfLastSegment(final int lastInterpolatedIndex,
+            final ResizableIntArray eventTimes, final ResizableIntArray xCoords,
+            final ResizableIntArray yCoords) {
+        if (!ENABLE_INTERPOLATION) {
+            return lastInterpolatedIndex;
+        }
+        final int size = mPreviewEventTimes.getLength();
+        final int[] pt = mPreviewEventTimes.getPrimitiveArray();
+        final int[] px = mPreviewXCoordinates.getPrimitiveArray();
+        final int[] py = mPreviewYCoordinates.getPrimitiveArray();
+        mInterpolator.reset(px, py, 0, size);
+        // The last segment of gesture stroke needs to be interpolated again because the slope of
+        // the tangent at the last point isn't determined.
+        int lastInterpolatedDrawIndex = lastInterpolatedIndex;
+        int d1 = lastInterpolatedIndex;
+        for (int p2 = mLastInterpolatedPreviewIndex + 1; p2 < size; p2++) {
+            final int p1 = p2 - 1;
+            final int p0 = p1 - 1;
+            final int p3 = p2 + 1;
+            mLastInterpolatedPreviewIndex = p1;
+            lastInterpolatedDrawIndex = d1;
+            mInterpolator.setInterval(p0, p1, p2, p3);
+            final double m1 = Math.atan2(mInterpolator.mSlope1Y, mInterpolator.mSlope1X);
+            final double m2 = Math.atan2(mInterpolator.mSlope2Y, mInterpolator.mSlope2X);
+            final double dm = Math.abs(angularDiff(m2, m1));
+            final int partition = Math.min((int)Math.ceil(dm / INTERPOLATION_ANGULAR_THRESHOLD),
+                    MAX_INTERPOLATION_PARTITION);
+            final int t1 = eventTimes.get(d1);
+            final int dt = pt[p2] - pt[p1];
+            d1++;
+            for (int i = 1; i < partition; i++) {
+                final float t = i / (float)partition;
+                mInterpolator.interpolate(t);
+                eventTimes.add(d1, (int)(dt * t) + t1);
+                xCoords.add(d1, (int)mInterpolator.mInterpolatedX);
+                yCoords.add(d1, (int)mInterpolator.mInterpolatedY);
+                d1++;
+            }
+            eventTimes.add(d1, pt[p2]);
+            xCoords.add(d1, px[p2]);
+            yCoords.add(d1, py[p2]);
+        }
+        return lastInterpolatedDrawIndex;
+    }
+
+    private static final double TWO_PI = Math.PI * 2.0d;
+
+    /**
+     * Calculate the angular of rotation from <code>a0</code> to <code>a1</code>.
+     *
+     * @param a1 the angular to which the rotation ends.
+     * @param a0 the angular from which the rotation starts.
+     * @return the angular rotation value from a0 to a1, normalized to [-PI, +PI].
+     */
+    private static double angularDiff(final double a1, final double a0) {
+        double deltaAngle = a1 - a0;
+        while (deltaAngle > Math.PI) {
+            deltaAngle -= TWO_PI;
+        }
+        while (deltaAngle < -Math.PI) {
+            deltaAngle += TWO_PI;
+        }
+        return deltaAngle;
+    }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java b/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java
new file mode 100644
index 0000000..0ec8153
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+/**
+ * Interpolates XY-coordinates using Cubic Hermite Curve.
+ */
+public final class HermiteInterpolator {
+    private int[] mXCoords;
+    private int[] mYCoords;
+    private int mMinPos;
+    private int mMaxPos;
+
+    // Working variable to calculate interpolated value.
+    /** The coordinates of the start point of the interval. */
+    public int mP1X, mP1Y;
+    /** The coordinates of the end point of the interval. */
+    public int mP2X, mP2Y;
+    /** The slope of the tangent at the start point. */
+    public float mSlope1X, mSlope1Y;
+    /** The slope of the tangent at the end point. */
+    public float mSlope2X, mSlope2Y;
+    /** The interpolated coordinates.
+     * The return variables of {@link #interpolate(float)} to avoid instantiations.
+     */
+    public float mInterpolatedX, mInterpolatedY;
+
+    public HermiteInterpolator() {
+        // Nothing to do with here.
+    }
+
+    /**
+     * Reset this interpolator to point XY-coordinates data.
+     * @param xCoords the array of x-coordinates. Valid data are in left-open interval
+     *                <code>[minPos, maxPos)</code>.
+     * @param yCoords the array of y-coordinates. Valid data are in left-open interval
+     *                <code>[minPos, maxPos)</code>.
+     * @param minPos the minimum index of left-open interval of valid data.
+     * @param maxPos the maximum index of left-open interval of valid data.
+     */
+    @UsedForTesting
+    public void reset(final int[] xCoords, final int[] yCoords, final int minPos,
+            final int maxPos) {
+        mXCoords = xCoords;
+        mYCoords = yCoords;
+        mMinPos = minPos;
+        mMaxPos = maxPos;
+    }
+
+    /**
+     * Set interpolation interval.
+     * <p>
+     * The start and end coordinates of the interval will be set in {@link #mP1X}, {@link #mP1Y},
+     * {@link #mP2X}, and {@link #mP2Y}. The slope of the tangents at start and end points will be
+     * set in {@link #mSlope1X}, {@link #mSlope1Y}, {@link #mSlope2X}, and {@link #mSlope2Y}.
+     *
+     * @param p0 the index just before interpolation interval. If <code>p1</code> points the start
+     *           of valid points, <code>p0</code> must be less than <code>minPos</code> of
+     *           {@link #reset(int[],int[],int,int)}.
+     * @param p1 the start index of interpolation interval.
+     * @param p2 the end index of interpolation interval.
+     * @param p3 the index just after interpolation interval. If <code>p2</code> points the end of
+     *           valid points, <code>p3</code> must be equal or greater than <code>maxPos</code> of
+     *           {@link #reset(int[],int[],int,int)}.
+     */
+    @UsedForTesting
+    public void setInterval(final int p0, final int p1, final int p2, final int p3) {
+        mP1X = mXCoords[p1];
+        mP1Y = mYCoords[p1];
+        mP2X = mXCoords[p2];
+        mP2Y = mYCoords[p2];
+        // A(ax,ay) is the vector p1->p2.
+        final int ax = mP2X - mP1X;
+        final int ay = mP2Y - mP1Y;
+
+        // Calculate the slope of the tangent at p1.
+        if (p0 >= mMinPos) {
+            // p1 has previous valid point p0.
+            // The slope of the tangent is half of the vector p0->p2.
+            mSlope1X = (mP2X - mXCoords[p0]) / 2.0f;
+            mSlope1Y = (mP2Y - mYCoords[p0]) / 2.0f;
+        } else if (p3 < mMaxPos) {
+            // p1 has no previous valid point, but p2 has next valid point p3.
+            // B(bx,by) is the slope vector of the tangent at p2.
+            final float bx = (mXCoords[p3] - mP1X) / 2.0f;
+            final float by = (mYCoords[p3] - mP1Y) / 2.0f;
+            final float crossProdAB = ax * by - ay * bx;
+            final float dotProdAB = ax * bx + ay * by;
+            final float normASquare = ax * ax + ay * ay;
+            final float invHalfNormASquare = 1.0f / normASquare / 2.0f;
+            // The slope of the tangent is the mirror image of vector B to vector A.
+            mSlope1X = invHalfNormASquare * (dotProdAB * ax + crossProdAB * ay);
+            mSlope1Y = invHalfNormASquare * (dotProdAB * ay - crossProdAB * ax);
+        } else {
+            // p1 and p2 have no previous valid point. (Interval has only point p1 and p2)
+            mSlope1X = ax;
+            mSlope1Y = ay;
+        }
+
+        // Calculate the slope of the tangent at p2.
+        if (p3 < mMaxPos) {
+            // p2 has next valid point p3.
+            // The slope of the tangent is half of the vector p1->p3.
+            mSlope2X = (mXCoords[p3] - mP1X) / 2.0f;
+            mSlope2Y = (mYCoords[p3] - mP1Y) / 2.0f;
+        } else if (p0 >= mMinPos) {
+            // p2 has no next valid point, but p1 has previous valid point p0.
+            // B(bx,by) is the slope vector of the tangent at p1.
+            final float bx = (mP2X - mXCoords[p0]) / 2.0f;
+            final float by = (mP2Y - mYCoords[p0]) / 2.0f;
+            final float crossProdAB = ax * by - ay * bx;
+            final float dotProdAB = ax * bx + ay * by;
+            final float normASquare = ax * ax + ay * ay;
+            final float invHalfNormASquare = 1.0f / normASquare / 2.0f;
+            // The slope of the tangent is the mirror image of vector B to vector A.
+            mSlope2X = invHalfNormASquare * (dotProdAB * ax + crossProdAB * ay);
+            mSlope2Y = invHalfNormASquare * (dotProdAB * ay - crossProdAB * ax);
+        } else {
+            // p1 and p2 has no previous valid point. (Interval has only point p1 and p2)
+            mSlope2X = ax;
+            mSlope2Y = ay;
+        }
+    }
+
+    /**
+     * Calculate interpolation value at <code>t</code> in unit interval <code>[0,1]</code>.
+     * <p>
+     * On the unit interval [0,1], given a starting point p1 at t=0 and an ending point p2 at t=1
+     * with the slope of the tangent m1 at p1 and m2 at p2, the polynomial of cubic Hermite curve
+     * can be defined by
+     *   p(t) = (1+2t)(1-t)(1-t)*p1 + t(1-t)(1-t)*m1 + (3-2t)t^2*p2 + (t-1)t^2*m2
+     * where t is an element of [0,1].
+     * <p>
+     * The interpolated XY-coordinates will be set in {@link #mInterpolatedX} and
+     * {@link #mInterpolatedY}.
+     *
+     * @param t the interpolation parameter. The value must be in close interval <code>[0,1]</code>.
+     */
+    @UsedForTesting
+    public void interpolate(final float t) {
+        final float omt = 1.0f - t;
+        final float tm2 = 2.0f * t;
+        final float k1 = 1.0f + tm2;
+        final float k2 = 3.0f - tm2;
+        final float omt2 = omt * omt;
+        final float t2 = t * t;
+        mInterpolatedX = (k1 * mP1X + t * mSlope1X) * omt2 + (k2 * mP2X - omt * mSlope2X) * t2;
+        mInterpolatedY = (k1 * mP1Y + t * mSlope1Y) * omt2 + (k2 * mP2Y - omt * mSlope2Y) * t2;
+    }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index 8ae1b88..be178f5 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -164,10 +164,10 @@
             parseKeyboard(parser);
         } catch (XmlPullParserException e) {
             Log.w(BUILDER_TAG, "keyboard XML parse error", e);
-            throw new IllegalArgumentException(e);
+            throw new IllegalArgumentException(e.getMessage(), e);
         } catch (IOException e) {
             Log.w(BUILDER_TAG, "keyboard XML parse error", e);
-            throw new RuntimeException(e);
+            throw new RuntimeException(e.getMessage(), e);
         } finally {
             parser.close();
         }
@@ -210,8 +210,8 @@
     private void parseKeyboard(final XmlPullParser parser)
             throws XmlPullParserException, IOException {
         if (DEBUG) startTag("<%s> %s", TAG_KEYBOARD, mParams.mId);
-        int event;
-        while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+        while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+            final int event = parser.next();
             if (event == XmlPullParser.START_TAG) {
                 final String tag = parser.getName();
                 if (TAG_KEYBOARD.equals(tag)) {
@@ -220,7 +220,7 @@
                     parseKeyboardContent(parser, false);
                     break;
                 } else {
-                    throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD);
+                    throw new XmlParseUtils.IllegalStartTag(parser, tag, TAG_KEYBOARD);
                 }
             }
         }
@@ -303,8 +303,8 @@
 
     private void parseKeyboardContent(final XmlPullParser parser, final boolean skip)
             throws XmlPullParserException, IOException {
-        int event;
-        while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+        while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+            final int event = parser.next();
             if (event == XmlPullParser.START_TAG) {
                 final String tag = parser.getName();
                 if (TAG_ROW.equals(tag)) {
@@ -321,7 +321,7 @@
                 } else if (TAG_KEY_STYLE.equals(tag)) {
                     parseKeyStyle(parser, skip);
                 } else {
-                    throw new XmlParseUtils.IllegalStartTag(parser, TAG_ROW);
+                    throw new XmlParseUtils.IllegalStartTag(parser, tag, TAG_ROW);
                 }
             } else if (event == XmlPullParser.END_TAG) {
                 final String tag = parser.getName();
@@ -333,7 +333,7 @@
                         || TAG_MERGE.equals(tag)) {
                     break;
                 } else {
-                    throw new XmlParseUtils.IllegalEndTag(parser, TAG_ROW);
+                    throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_ROW);
                 }
             }
         }
@@ -345,10 +345,10 @@
                 R.styleable.Keyboard);
         try {
             if (a.hasValue(R.styleable.Keyboard_horizontalGap)) {
-                throw new XmlParseUtils.IllegalAttribute(parser, "horizontalGap");
+                throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "horizontalGap");
             }
             if (a.hasValue(R.styleable.Keyboard_verticalGap)) {
-                throw new XmlParseUtils.IllegalAttribute(parser, "verticalGap");
+                throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "verticalGap");
             }
             return new KeyboardRow(mResources, mParams, parser, mCurrentY);
         } finally {
@@ -358,8 +358,8 @@
 
     private void parseRowContent(final XmlPullParser parser, final KeyboardRow row,
             final boolean skip) throws XmlPullParserException, IOException {
-        int event;
-        while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+        while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+            final int event = parser.next();
             if (event == XmlPullParser.START_TAG) {
                 final String tag = parser.getName();
                 if (TAG_KEY.equals(tag)) {
@@ -373,7 +373,7 @@
                 } else if (TAG_KEY_STYLE.equals(tag)) {
                     parseKeyStyle(parser, skip);
                 } else {
-                    throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
+                    throw new XmlParseUtils.IllegalStartTag(parser, tag, TAG_ROW);
                 }
             } else if (event == XmlPullParser.END_TAG) {
                 final String tag = parser.getName();
@@ -387,7 +387,7 @@
                         || TAG_MERGE.equals(tag)) {
                     break;
                 } else {
-                    throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
+                    throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_ROW);
                 }
             }
         }
@@ -506,8 +506,8 @@
     private void parseMerge(final XmlPullParser parser, final KeyboardRow row, final boolean skip)
             throws XmlPullParserException, IOException {
         if (DEBUG) startTag("<%s>", TAG_MERGE);
-        int event;
-        while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+        while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+            final int event = parser.next();
             if (event == XmlPullParser.START_TAG) {
                 final String tag = parser.getName();
                 if (TAG_MERGE.equals(tag)) {
@@ -539,8 +539,8 @@
             final boolean skip) throws XmlPullParserException, IOException {
         if (DEBUG) startTag("<%s> %s", TAG_SWITCH, mParams.mId);
         boolean selected = false;
-        int event;
-        while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+        while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+            final int event = parser.next();
             if (event == XmlPullParser.START_TAG) {
                 final String tag = parser.getName();
                 if (TAG_CASE.equals(tag)) {
@@ -548,7 +548,7 @@
                 } else if (TAG_DEFAULT.equals(tag)) {
                     selected |= parseDefault(parser, row, selected ? true : skip);
                 } else {
-                    throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
+                    throw new XmlParseUtils.IllegalStartTag(parser, tag, TAG_SWITCH);
                 }
             } else if (event == XmlPullParser.END_TAG) {
                 final String tag = parser.getName();
@@ -556,7 +556,7 @@
                     if (DEBUG) endTag("</%s>", TAG_SWITCH);
                     break;
                 } else {
-                    throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
+                    throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_SWITCH);
                 }
             }
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index d0b382e..7ec1c94 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -21,7 +21,6 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.R;
 
 import java.util.HashMap;
 
@@ -61,13 +60,14 @@
         }
     }
 
-    public void loadStringResources(Context context) {
-        loadStringResourcesInternal(context, RESOURCE_NAMES, R.string.english_ime_name);
+    public void loadStringResources(final Context context) {
+        final int referenceId = context.getApplicationInfo().labelRes;
+        loadStringResourcesInternal(context, RESOURCE_NAMES, referenceId);
     }
 
     @UsedForTesting
-    void loadStringResourcesInternal(Context context, final String[] resourceNames,
-            int referenceId) {
+    void loadStringResourcesInternal(final Context context, final String[] resourceNames,
+            final int referenceId) {
         final Resources res = context.getResources();
         final String packageName = res.getResourcePackageName(referenceId);
         for (final String resName : resourceNames) {
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 4bec99c..562e1d0 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -450,4 +450,25 @@
                     info.toContentValues());
         }
     }
+
+    /**
+     * Initialize a client record with the dictionary content provider.
+     *
+     * This merely acquires the content provider and calls
+     * #reinitializeClientRecordInDictionaryContentProvider.
+     *
+     * @param context the context for resources and providers.
+     * @param clientId the client ID to use.
+     */
+    public static void initializeClientRecordHelper(final Context context,
+            final String clientId) {
+        try {
+            final ContentProviderClient client = context.getContentResolver().
+                    acquireContentProviderClient(getProviderUriBuilder("").build());
+            if (null == client) return;
+            reinitializeClientRecordInDictionaryContentProvider(context, client, clientId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Cannot contact the dictionary content provider", e);
+        }
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
index 35f3119..41fcb83 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
@@ -25,14 +25,35 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.net.Uri;
+import android.util.Log;
 
 /**
- * Takes action to reload the necessary data when a dictionary pack was added/removed.
+ * Receives broadcasts pertaining to dictionary management and takes the appropriate action.
+ *
+ * This object receives three types of broadcasts.
+ * - Package installed/added. When a dictionary provider application is added or removed, we
+ * need to query the dictionaries.
+ * - New dictionary broadcast. The dictionary provider broadcasts new dictionary availability. When
+ * this happens, we need to re-query the dictionaries.
+ * - Unknown client. If the dictionary provider is in urgent need of data about some client that
+ * it does not know, it sends this broadcast. When we receive this, we need to tell the dictionary
+ * provider about ourselves. This happens when the settings for the dictionary pack are accessed,
+ * but Latin IME never got a chance to register itself.
  */
 public final class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver {
+    private static final String TAG = DictionaryPackInstallBroadcastReceiver.class.getSimpleName();
 
     final LatinIME mService;
 
+    public DictionaryPackInstallBroadcastReceiver() {
+        // This empty constructor is necessary for the system to instantiate this receiver.
+        // This happens when the dictionary pack says it can't find a record for our client,
+        // which happens when the dictionary pack settings are called before the keyboard
+        // was ever started once.
+        Log.i(TAG, "Latin IME dictionary broadcast receiver instantiated from the framework.");
+        mService = null;
+    }
+
     public DictionaryPackInstallBroadcastReceiver(final LatinIME service) {
         mService = service;
     }
@@ -44,6 +65,11 @@
 
         // We need to reread the dictionary if a new dictionary package is installed.
         if (action.equals(Intent.ACTION_PACKAGE_ADDED)) {
+            if (null == mService) {
+                Log.e(TAG, "Called with intent " + action + " but we don't know the service: this "
+                        + "should never happen");
+                return;
+            }
             final Uri packageUri = intent.getData();
             if (null == packageUri) return; // No package name : we can't do anything
             final String packageName = packageUri.getSchemeSpecificPart();
@@ -71,6 +97,11 @@
             return;
         } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
                 && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+            if (null == mService) {
+                Log.e(TAG, "Called with intent " + action + " but we don't know the service: this "
+                        + "should never happen");
+                return;
+            }
             // When the dictionary package is removed, we need to reread dictionary (to use the
             // next-priority one, or stop using a dictionary at all if this was the only one,
             // since this is the user request).
@@ -82,7 +113,28 @@
             // read dictionary from?
             mService.resetSuggestMainDict();
         } else if (action.equals(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)) {
+            if (null == mService) {
+                Log.e(TAG, "Called with intent " + action + " but we don't know the service: this "
+                        + "should never happen");
+                return;
+            }
             mService.resetSuggestMainDict();
+        } else if (action.equals(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT)) {
+            if (null != mService) {
+                // Careful! This is returning if the service is NOT null. This is because we
+                // should come here instantiated by the framework in reaction to a broadcast of
+                // the above action, so we should gave gone through the no-args constructor.
+                Log.e(TAG, "Called with intent " + action + " but we have a reference to the "
+                        + "service: this should never happen");
+                return;
+            }
+            // The dictionary provider does not know about some client. We check that it's really
+            // us that it needs to know about, and if it's the case, we register with the provider.
+            final String wantedClientId =
+                    intent.getStringExtra(DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA);
+            final String myClientId = context.getString(R.string.dictionary_pack_client_id);
+            if (!wantedClientId.equals(myClientId)) return; // Not for us
+            BinaryDictionaryFileDumper.initializeClientRecordHelper(context, myClientId);
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index ae2ee57..fd81d13 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
@@ -31,6 +32,7 @@
  * be searched for suggestions and valid words.
  */
 public class ExpandableDictionary extends Dictionary {
+    private static final String TAG = ExpandableDictionary.class.getSimpleName();
     /**
      * The weight to give to a word if it's length is the same as the number of typed characters.
      */
@@ -551,8 +553,13 @@
         // word. We do want however to return the correct case for the right hand side.
         // So we want to squash the case of the left hand side, and preserve that of the right
         // hand side word.
-        Node firstWord = searchWord(mRoots, word1.toLowerCase(), 0, null);
-        Node secondWord = searchWord(mRoots, word2, 0, null);
+        final String word1Lower = word1.toLowerCase();
+        if (TextUtils.isEmpty(word1Lower) || TextUtils.isEmpty(word2)) {
+            Log.e(TAG, "Invalid bigram pair: " + word1 + ", " + word1Lower + ", " + word2);
+            return frequency;
+        }
+        final Node firstWord = searchWord(mRoots, word1Lower, 0, null);
+        final Node secondWord = searchWord(mRoots, word2, 0, null);
         LinkedList<NextWord> bigrams = firstWord.mNGrams;
         if (bigrams == null || bigrams.size() == 0) {
             firstWord.mNGrams = CollectionUtils.newLinkedList();
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index e3650d9..56b1c78 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -72,6 +72,7 @@
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.keyboard.MainKeyboardView;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.Utils.Stats;
 import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.suggestions.SuggestionStripView;
@@ -156,7 +157,7 @@
     private PositionalInfoForUserDictPendingAddition
             mPositionalInfoForUserDictPendingAddition = null;
     private final WordComposer mWordComposer = new WordComposer();
-    private RichInputConnection mConnection = new RichInputConnection(this);
+    private final RichInputConnection mConnection = new RichInputConnection(this);
 
     // Keep track of the last selection range to decide if we need to show word alternatives
     private static final int NOT_A_CURSOR_POSITION = -1;
@@ -803,10 +804,6 @@
 
     @Override
     public void onWindowHidden() {
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_onWindowHidden(mLastSelectionStart, mLastSelectionEnd,
-                    getCurrentInputConnection());
-        }
         super.onWindowHidden();
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
         if (mainKeyboardView != null) {
@@ -834,8 +831,10 @@
         // Remove pending messages related to update suggestions
         mHandler.cancelUpdateSuggestionStrip();
         resetComposingState(true /* alsoResetLastComposedWord */);
+        // Notify ResearchLogger
         if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.getInstance().latinIME_onFinishInputViewInternal();
+            ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput, mLastSelectionStart,
+                    mLastSelectionEnd, getCurrentInputConnection());
         }
     }
 
@@ -1145,11 +1144,11 @@
         if (!mWordComposer.isComposingWord()) return;
         final String typedWord = mWordComposer.getTypedWord();
         if (typedWord.length() > 0) {
-            commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD,
-                    separatorString);
             if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                 ResearchLogger.getInstance().onWordFinished(typedWord, mWordComposer.isBatchMode());
             }
+            commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD,
+                    separatorString);
         }
     }
 
@@ -1907,7 +1906,6 @@
     private boolean handleSeparator(final int primaryCode, final int x, final int y,
             final int spaceState) {
         if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.recordTimeForLogUnitSplit();
             ResearchLogger.latinIME_handleSeparator(primaryCode, mWordComposer.isComposingWord());
         }
         boolean didAutoCorrect = false;
@@ -2176,8 +2174,9 @@
     // Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener}
     // interface
     @Override
-    public void pickSuggestionManually(final int index, final String suggestion) {
+    public void pickSuggestionManually(final int index, final SuggestedWordInfo suggestionInfo) {
         final SuggestedWords suggestedWords = mSuggestedWords;
+        final String suggestion = suggestionInfo.mWord;
         // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
         if (suggestion.length() == 1 && isShowingPunctuationList()) {
             // Word separators are suggested before the user inputs something.
@@ -2243,7 +2242,8 @@
         // AND it's in none of our current dictionaries (main, user or otherwise).
         // Please note that if mSuggest is null, it means that everything is off: suggestion
         // and correction, so we shouldn't try to show the hint
-        final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null
+        final boolean showingAddToDictionaryHint =
+                SuggestedWordInfo.KIND_TYPED == suggestionInfo.mKind && mSuggest != null
                 // If the suggestion is not in the dictionary, the hint should be shown.
                 && !AutoCorrection.isValidWord(mSuggest.getUnigramDictionaries(), suggestion, true);
 
@@ -2297,25 +2297,27 @@
         // expect to receive non-words.
         if (!mSettings.getCurrent().mCorrectionEnabled) return null;
 
+        final Suggest suggest = mSuggest;
         final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary;
-        if (userHistoryDictionary != null) {
-            final String prevWord
-                    = mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators, 2);
-            final String secondWord;
-            if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
-                secondWord = suggestion.toLowerCase(mSubtypeSwitcher.getCurrentSubtypeLocale());
-            } else {
-                secondWord = suggestion;
-            }
-            // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
-            // We don't add words with 0-frequency (assuming they would be profanity etc.).
-            final int maxFreq = AutoCorrection.getMaxFrequency(
-                    mSuggest.getUnigramDictionaries(), suggestion);
-            if (maxFreq == 0) return null;
-            userHistoryDictionary.addToUserHistory(prevWord, secondWord, maxFreq > 0);
-            return prevWord;
+        if (suggest == null || userHistoryDictionary == null) {
+            // Avoid concurrent issue
+            return null;
         }
-        return null;
+        final String prevWord
+                = mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators, 2);
+        final String secondWord;
+        if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
+            secondWord = suggestion.toLowerCase(mSubtypeSwitcher.getCurrentSubtypeLocale());
+        } else {
+            secondWord = suggestion;
+        }
+        // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
+        // We don't add words with 0-frequency (assuming they would be profanity etc.).
+        final int maxFreq = AutoCorrection.getMaxFrequency(
+                suggest.getUnigramDictionaries(), suggestion);
+        if (maxFreq == 0) return null;
+        userHistoryDictionary.addToUserHistory(prevWord, secondWord, maxFreq > 0);
+        return prevWord;
     }
 
     /**
@@ -2526,7 +2528,7 @@
         final CharSequence[] items = new CharSequence[] {
                 // TODO: Should use new string "Select active input modes".
                 getString(R.string.language_selection_title),
-                getString(R.string.english_ime_settings),
+                getString(Utils.getAcitivityTitleResId(this, SettingsActivity.class)),
         };
         final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
             @Override
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 8a7ade4..16744d1 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -60,11 +60,11 @@
      * This contains the committed text immediately preceding the cursor and the composing
      * text if any. It is refreshed when the cursor moves by calling upon the TextView.
      */
-    private StringBuilder mCommittedTextBeforeComposingText = new StringBuilder();
+    private final StringBuilder mCommittedTextBeforeComposingText = new StringBuilder();
     /**
      * This contains the currently composing text, as LatinIME thinks the TextView is seeing it.
      */
-    private StringBuilder mComposingText = new StringBuilder();
+    private final StringBuilder mComposingText = new StringBuilder();
     // A hint on how many characters to cache from the TextView. A good value of this is given by
     // how many characters we need to be able to almost always find the caps mode.
     private static final int DEFAULT_TEXT_CACHE_SIZE = 100;
@@ -334,13 +334,15 @@
         mCurrentCursorPosition = end;
         final CharSequence textBeforeCursor =
                 getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE + (end - start), 0);
-        final int indexOfStartOfComposingText =
-                Math.max(textBeforeCursor.length() - (end - start), 0);
-        mComposingText.append(textBeforeCursor.subSequence(indexOfStartOfComposingText,
-                textBeforeCursor.length()));
         mCommittedTextBeforeComposingText.setLength(0);
-        mCommittedTextBeforeComposingText.append(
-                textBeforeCursor.subSequence(0, indexOfStartOfComposingText));
+        if (!TextUtils.isEmpty(textBeforeCursor)) {
+            final int indexOfStartOfComposingText =
+                    Math.max(textBeforeCursor.length() - (end - start), 0);
+            mComposingText.append(textBeforeCursor.subSequence(indexOfStartOfComposingText,
+                    textBeforeCursor.length()));
+            mCommittedTextBeforeComposingText.append(
+                    textBeforeCursor.subSequence(0, indexOfStartOfComposingText));
+        }
         if (null != mIC) {
             mIC.setComposingRegion(start, end);
         }
@@ -502,16 +504,6 @@
         return (r == null) ? null : r.mWord;
     }
 
-    private int getCursorPosition() {
-        mIC = mParent.getCurrentInputConnection();
-        if (null == mIC) return INVALID_CURSOR_POSITION;
-        final ExtractedText extracted = mIC.getExtractedText(new ExtractedTextRequest(), 0);
-        if (extracted == null) {
-            return INVALID_CURSOR_POSITION;
-        }
-        return extracted.startOffset + extracted.selectionStart;
-    }
-
     /**
      * Returns the text surrounding the cursor.
      *
diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java
index 4fdd839..928141c 100644
--- a/java/src/com/android/inputmethod/latin/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java
@@ -69,6 +69,11 @@
         setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
         setSubtypeEnablerTitle(R.string.select_language);
         addPreferencesFromResource(R.xml.prefs);
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            preferenceScreen.setTitle(
+                    Utils.getAcitivityTitleResId(getActivity(), SettingsActivity.class));
+        }
 
         final Resources res = getResources();
         final Context context = getActivity();
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index 90c3fcd..59ad28f 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -22,6 +22,10 @@
 import java.util.Locale;
 
 public final class StringUtils {
+    public static final int CAPITALIZE_NONE = 0;  // No caps, or mixed case
+    public static final int CAPITALIZE_FIRST = 1; // First only
+    public static final int CAPITALIZE_ALL = 2;   // All caps
+
     private StringUtils() {
         // This utility class is not publicly instantiable.
     }
@@ -111,11 +115,12 @@
         // - This does not work for Greek, because it returns upper case instead of title case.
         // - It does not work for Serbian, because it fails to account for the "lj" character,
         // which should be "Lj" in title case and "LJ" in upper case.
-        // - It does not work for Dutch, because it fails to account for the "ij" digraph, which
-        // are two different characters but both should be capitalized as "IJ" as if they were
-        // a single letter.
-        // - It also does not work with unicode surrogate code points.
-        return s.toUpperCase(locale).charAt(0) + s.substring(1);
+        // - It does not work for Dutch, because it fails to account for the "ij" digraph when it's
+        // written as two separate code points. They are two different characters but both should
+        // be capitalized as "IJ" as if they were a single letter in most words (not all). If the
+        // unicode char for the ligature is used however, it works.
+        final int cutoff = s.offsetByCodePoints(0, 1);
+        return s.substring(0, cutoff).toUpperCase(locale) + s.substring(cutoff).toLowerCase(locale);
     }
 
     private static final int[] EMPTY_CODEPOINTS = {};
@@ -171,4 +176,41 @@
         }
         return list.toArray(new String[list.size()]);
     }
+
+    // This method assumes the text is not null. For the empty string, it returns CAPITALIZE_NONE.
+    public static int getCapitalizationType(final String text) {
+        // If the first char is not uppercase, then the word is either all lower case or
+        // camel case, and in either case we return CAPITALIZE_NONE.
+        final int len = text.length();
+        int index = 0;
+        for (; index < len; index = text.offsetByCodePoints(index, 1)) {
+            if (Character.isLetter(text.codePointAt(index))) {
+                break;
+            }
+        }
+        if (index == len) return CAPITALIZE_NONE;
+        if (!Character.isUpperCase(text.codePointAt(index))) {
+            return CAPITALIZE_NONE;
+        }
+        int capsCount = 1;
+        int letterCount = 1;
+        for (index = text.offsetByCodePoints(index, 1); index < len;
+                index = text.offsetByCodePoints(index, 1)) {
+            if (1 != capsCount && letterCount != capsCount) break;
+            final int codePoint = text.codePointAt(index);
+            if (Character.isUpperCase(codePoint)) {
+                ++capsCount;
+                ++letterCount;
+            } else if (Character.isLetter(codePoint)) {
+                // We need to discount non-letters since they may not be upper-case, but may
+                // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
+                ++letterCount;
+            }
+        }
+        // We know the first char is upper case. So we want to test if either every letter other
+        // than the first is lower case, or if they are all upper case. If the string is exactly
+        // one char long, then we will arrive here with letterCount 1, and this is correct, too.
+        if (1 == capsCount) return CAPITALIZE_FIRST;
+        return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 9cbfe66..5e28cc2 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -114,7 +114,7 @@
 
         final String[] keyboardLayoutSetMap = res.getStringArray(
                 R.array.locale_and_extra_value_to_keyboard_layout_set_map);
-        for (int i = 0; i < keyboardLayoutSetMap.length; i += 2) {
+        for (int i = 0; i + 1 < keyboardLayoutSetMap.length; i += 2) {
             final String key = keyboardLayoutSetMap[i];
             final String keyboardLayoutSet = keyboardLayoutSetMap[i + 1];
             sLocaleAndExtraValueToKeyboardLayoutSetMap.put(key, keyboardLayoutSet);
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
index 62f2a97..1093155 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
@@ -207,7 +207,12 @@
             final ArrayList<PendingAttribute> attrList = bigrams.get(entry.getKey());
             if (attrList != null) {
                 for (final PendingAttribute attr : attrList) {
-                    to.setBigram(word1, unigrams.get(attr.mAddress),
+                    final String word2 = unigrams.get(attr.mAddress);
+                    if (word1 == null || word2 == null) {
+                        Log.e(TAG, "Invalid bigram pair detected: " + word1 + ", " + word2);
+                        continue;
+                    }
+                    to.setBigram(word1, word2,
                             BinaryDictInputOutput.reconstructBigramFrequency(unigramFrequency,
                                     attr.mFrequency));
                 }
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 7a604dc..aff5d17 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -16,8 +16,13 @@
 
 package com.android.inputmethod.latin;
 
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -45,6 +50,8 @@
 import java.util.Locale;
 
 public final class Utils {
+    private static final String TAG = Utils.class.getSimpleName();
+
     private Utils() {
         // This utility class is not publicly instantiable.
     }
@@ -453,4 +460,17 @@
         if (TextUtils.isEmpty(info)) return null;
         return info;
     }
+
+    public static int getAcitivityTitleResId(Context context, Class<? extends Activity> cls) {
+        final ComponentName cn = new ComponentName(context, cls);
+        try {
+            final ActivityInfo ai = context.getPackageManager().getActivityInfo(cn, 0);
+            if (ai != null) {
+                return ai.labelRes;
+            }
+        } catch (NameNotFoundException e) {
+            Log.e(TAG, "Failed to get settings activity title res id.", e);
+        }
+        return 0;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/XmlParseUtils.java b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
index f01d4c5..48e5ed3 100644
--- a/java/src/com/android/inputmethod/latin/XmlParseUtils.java
+++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
@@ -30,50 +30,53 @@
 
     @SuppressWarnings("serial")
     public static class ParseException extends XmlPullParserException {
-        public ParseException(String msg, XmlPullParser parser) {
+        public ParseException(final String msg, final XmlPullParser parser) {
             super(msg + " at " + parser.getPositionDescription());
         }
     }
 
     @SuppressWarnings("serial")
     public static final class IllegalStartTag extends ParseException {
-        public IllegalStartTag(XmlPullParser parser, String parent) {
-            super("Illegal start tag " + parser.getName() + " in " + parent, parser);
+        public IllegalStartTag(final XmlPullParser parser, final String tag, final String parent) {
+            super("Illegal start tag " + tag + " in " + parent, parser);
         }
     }
 
     @SuppressWarnings("serial")
     public static final class IllegalEndTag extends ParseException {
-        public IllegalEndTag(XmlPullParser parser, String parent) {
-            super("Illegal end tag " + parser.getName() + " in " + parent, parser);
+        public IllegalEndTag(final XmlPullParser parser, final String tag, final String parent) {
+            super("Illegal end tag " + tag + " in " + parent, parser);
         }
     }
 
     @SuppressWarnings("serial")
     public static final class IllegalAttribute extends ParseException {
-        public IllegalAttribute(XmlPullParser parser, String attribute) {
-            super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
+        public IllegalAttribute(final XmlPullParser parser, final String tag,
+                final String attribute) {
+            super("Tag " + tag + " has illegal attribute " + attribute, parser);
         }
     }
 
     @SuppressWarnings("serial")
     public static final class NonEmptyTag extends ParseException{
-        public NonEmptyTag(String tag, XmlPullParser parser) {
+        public NonEmptyTag(final XmlPullParser parser, final String tag) {
             super(tag + " must be empty tag", parser);
         }
     }
 
-    public static void checkEndTag(String tag, XmlPullParser parser)
+    public static void checkEndTag(final String tag, final XmlPullParser parser)
             throws XmlPullParserException, IOException {
         if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
             return;
-        throw new NonEmptyTag(tag, parser);
+        throw new NonEmptyTag(parser, tag);
     }
 
-    public static void checkAttributeExists(TypedArray attr, int attrId, String attrName,
-            String tag, XmlPullParser parser) throws XmlPullParserException {
-        if (attr.hasValue(attrId))
+    public static void checkAttributeExists(final TypedArray attr, final int attrId,
+            final String attrName, final String tag, final XmlPullParser parser)
+                    throws XmlPullParserException {
+        if (attr.hasValue(attrId)) {
             return;
+        }
         throw new ParseException(
                 "No " + attrName + " attribute found in <" + tag + "/>", parser);
     }
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
index 699e47b..dc937fb 100644
--- a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
@@ -28,5 +28,5 @@
     // USES_DEVELOPMENT_ONLY_DIAGNOSTICS must be false for any production build.
     public static final boolean USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG = false;
 
-    public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = true;
+    public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false;
 }
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index 5c80559..e7c7e2b 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -620,34 +620,34 @@
      * Helper method to find a word in a given branch.
      */
     @SuppressWarnings("unused")
-    public static CharGroup findWordInTree(Node node, final String s) {
+    public static CharGroup findWordInTree(Node node, final String string) {
         int index = 0;
         final StringBuilder checker = DBG ? new StringBuilder() : null;
+        final int[] codePoints = getCodePoints(string);
 
         CharGroup currentGroup;
-        final int codePointCountInS = s.codePointCount(0, s.length());
         do {
-            int indexOfGroup = findIndexOfChar(node, s.codePointAt(index));
+            int indexOfGroup = findIndexOfChar(node, codePoints[index]);
             if (CHARACTER_NOT_FOUND == indexOfGroup) return null;
             currentGroup = node.mData.get(indexOfGroup);
 
-            if (s.length() - index < currentGroup.mChars.length) return null;
+            if (codePoints.length - index < currentGroup.mChars.length) return null;
             int newIndex = index;
-            while (newIndex < s.length() && newIndex - index < currentGroup.mChars.length) {
-                if (currentGroup.mChars[newIndex - index] != s.codePointAt(newIndex)) return null;
+            while (newIndex < codePoints.length && newIndex - index < currentGroup.mChars.length) {
+                if (currentGroup.mChars[newIndex - index] != codePoints[newIndex]) return null;
                 newIndex++;
             }
             index = newIndex;
 
             if (DBG) checker.append(new String(currentGroup.mChars, 0, currentGroup.mChars.length));
-            if (index < codePointCountInS) {
+            if (index < codePoints.length) {
                 node = currentGroup.mChildren;
             }
-        } while (null != node && index < codePointCountInS);
+        } while (null != node && index < codePoints.length);
 
-        if (index < codePointCountInS) return null;
+        if (index < codePoints.length) return null;
         if (!currentGroup.isTerminal()) return null;
-        if (DBG && !s.equals(checker.toString())) return null;
+        if (DBG && !codePoints.equals(checker.toString())) return null;
         return currentGroup;
     }
 
@@ -847,12 +847,12 @@
         @Override
         public Word next() {
             Position currentPos = mPositions.getLast();
-            mCurrentString.setLength(mCurrentString.length() - currentPos.length);
+            mCurrentString.setLength(currentPos.length);
 
             do {
                 if (currentPos.pos.hasNext()) {
                     final CharGroup currentGroup = currentPos.pos.next();
-                    currentPos.length = currentGroup.mChars.length;
+                    currentPos.length = mCurrentString.length();
                     for (int i : currentGroup.mChars)
                         mCurrentString.append(Character.toChars(i));
                     if (null != currentGroup.mChildren) {
@@ -866,7 +866,7 @@
                 } else {
                     mPositions.removeLast();
                     currentPos = mPositions.getLast();
-                    mCurrentString.setLength(mCurrentString.length() - mPositions.getLast().length);
+                    mCurrentString.setLength(mPositions.getLast().length);
                 }
             } while (true);
         }
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index 7f66c6d..15d0bac 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -112,12 +112,13 @@
         // TODO: Use sans-serif-thin font family depending on the system locale white list and
         // the SDK version.
         final TextView titleView = (TextView)findViewById(R.id.setup_title);
-        titleView.setText(getString(R.string.setup_title, getString(R.string.english_ime_name)));
+        final int appName = getApplicationInfo().labelRes;
+        titleView.setText(getString(R.string.setup_title, getString(appName)));
 
         mStepIndicatorView = (SetupStepIndicatorView)findViewById(R.id.setup_step_indicator);
 
         final SetupStep step1 = new SetupStep(findViewById(R.id.setup_step1),
-                R.string.setup_step1_title, R.string.setup_step1_instruction,
+                appName, R.string.setup_step1_title, R.string.setup_step1_instruction,
                 R.drawable.ic_settings_language, R.string.language_settings);
         step1.setAction(new Runnable() {
             @Override
@@ -129,7 +130,7 @@
         mSetupSteps.addStep(STEP_1, step1);
 
         final SetupStep step2 = new SetupStep(findViewById(R.id.setup_step2),
-                R.string.setup_step2_title, R.string.setup_step2_instruction,
+                appName, R.string.setup_step2_title, R.string.setup_step2_instruction,
                 0 /* actionIcon */, R.string.select_input_method);
         step2.setAction(new Runnable() {
             @Override
@@ -142,7 +143,7 @@
         mSetupSteps.addStep(STEP_2, step2);
 
         final SetupStep step3 = new SetupStep(findViewById(R.id.setup_step3),
-                R.string.setup_step3_title, 0 /* instruction */,
+                appName, R.string.setup_step3_title, 0 /* instruction */,
                 R.drawable.sym_keyboard_language_switch, R.string.setup_step3_instruction);
         step3.setAction(new Runnable() {
             @Override
@@ -290,11 +291,11 @@
         private final TextView mActionLabel;
         private Runnable mAction;
 
-        public SetupStep(final View rootView, final int title, final int instruction,
-                final int actionIcon, final int actionLabel) {
+        public SetupStep(final View rootView, final int appName, final int title,
+                final int instruction, final int actionIcon, final int actionLabel) {
             mRootView = rootView;
             final Resources res = rootView.getResources();
-            final String applicationName = res.getString(R.string.english_ime_name);
+            final String applicationName = res.getString(appName);
 
             final TextView titleView = (TextView)rootView.findViewById(R.id.setup_step_title);
             titleView.setText(res.getString(title, applicationName));
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 97e280d..fbed139 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -58,10 +58,6 @@
 
     public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
 
-    public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
-    public static final int CAPITALIZE_FIRST = 1; // First only
-    public static final int CAPITALIZE_ALL = 2; // All caps
-
     private final static String[] EMPTY_STRING_ARRAY = new String[0];
     private Map<String, DictionaryPool> mDictionaryPools = CollectionUtils.newSynchronizedTreeMap();
     private Map<String, UserBinaryDictionary> mUserDictionaries =
@@ -325,13 +321,13 @@
                 }
                 Collections.reverse(mSuggestions);
                 StringUtils.removeDupes(mSuggestions);
-                if (CAPITALIZE_ALL == capitalizeType) {
+                if (StringUtils.CAPITALIZE_ALL == capitalizeType) {
                     for (int i = 0; i < mSuggestions.size(); ++i) {
                         // get(i) returns a CharSequence which is actually a String so .toString()
                         // should return the same object.
                         mSuggestions.set(i, mSuggestions.get(i).toString().toUpperCase(locale));
                     }
-                } else if (CAPITALIZE_FIRST == capitalizeType) {
+                } else if (StringUtils.CAPITALIZE_FIRST == capitalizeType) {
                     for (int i = 0; i < mSuggestions.size(); ++i) {
                         // Likewise
                         mSuggestions.set(i, StringUtils.toTitleCase(
@@ -434,31 +430,4 @@
         }
         return new DictAndProximity(dictionaryCollection, proximityInfo);
     }
-
-    // This method assumes the text is not empty or null.
-    public static int getCapitalizationType(String text) {
-        // If the first char is not uppercase, then the word is either all lower case,
-        // and in either case we return CAPITALIZE_NONE.
-        if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
-        final int len = text.length();
-        int capsCount = 1;
-        int letterCount = 1;
-        for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
-            if (1 != capsCount && letterCount != capsCount) break;
-            final int codePoint = text.codePointAt(i);
-            if (Character.isUpperCase(codePoint)) {
-                ++capsCount;
-                ++letterCount;
-            } else if (Character.isLetter(codePoint)) {
-                // We need to discount non-letters since they may not be upper-case, but may
-                // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
-                ++letterCount;
-            }
-        }
-        // We know the first char is upper case. So we want to test if either every letter other
-        // than the first is lower case, or if they are all upper case. If the string is exactly
-        // one char long, then we will arrive here with letterCount 1, and this is correct, too.
-        if (1 == capsCount) return CAPITALIZE_FIRST;
-        return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 4f86a31..b150632 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -150,7 +150,7 @@
             // Greek letters are either in the 370~3FF range (Greek & Coptic), or in the
             // 1F00~1FFF range (Greek extended). Our dictionary contains both sort of characters.
             // Our dictionary also contains a few words with 0xF2; it would be best to check
-            // if that's correct, but a Google search does return results for these words so
+            // if that's correct, but a web search does return results for these words so
             // they are probably okay.
             return (codePoint >= 0x370 && codePoint <= 0x3FF)
                     || (codePoint >= 0x1F00 && codePoint <= 0x1FFF)
@@ -214,14 +214,14 @@
         // If the word is in there as is, then it's in the dictionary. If not, we'll test lower
         // case versions, but only if the word is not already all-lower case or mixed case.
         if (dict.isValidWord(text)) return true;
-        if (AndroidSpellCheckerService.CAPITALIZE_NONE == capitalizeType) return false;
+        if (StringUtils.CAPITALIZE_NONE == capitalizeType) return false;
 
         // If we come here, we have a capitalized word (either First- or All-).
         // Downcase the word and look it up again. If the word is only capitalized, we
         // tested all possibilities, so if it's still negative we can return false.
         final String lowerCaseText = text.toLowerCase(mLocale);
         if (dict.isValidWord(lowerCaseText)) return true;
-        if (AndroidSpellCheckerService.CAPITALIZE_FIRST == capitalizeType) return false;
+        if (StringUtils.CAPITALIZE_FIRST == capitalizeType) return false;
 
         // If the lower case version is not in the dictionary, it's still possible
         // that we have an all-caps version of a word that needs to be capitalized
@@ -296,7 +296,7 @@
                 }
             }
 
-            final int capitalizeType = AndroidSpellCheckerService.getCapitalizationType(text);
+            final int capitalizeType = StringUtils.getCapitalizationType(text);
             boolean isInDict = true;
             DictAndProximity dictInfo = null;
             try {
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
index 9606b03..5ce9d8e 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
@@ -18,8 +18,10 @@
 
 import android.os.Bundle;
 import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
 
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.Utils;
 
 /**
  * Preference screen.
@@ -35,5 +37,10 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         addPreferencesFromResource(R.xml.spell_checker_settings);
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            preferenceScreen.setTitle(Utils.getAcitivityTitleResId(
+                    getActivity(), SpellCheckerSettingsActivity.class));
+        }
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 8c3d3b0..eeaf828 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -62,6 +62,7 @@
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.ResourceUtils;
 import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.research.ResearchLogger;
@@ -72,7 +73,7 @@
         OnLongClickListener {
     public interface Listener {
         public void addWordToUserDictionary(String word);
-        public void pickSuggestionManually(int index, String word);
+        public void pickSuggestionManually(int index, SuggestedWordInfo word);
     }
 
     // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}.
@@ -656,8 +657,8 @@
         @Override
         public boolean onCustomRequest(final int requestCode) {
             final int index = requestCode;
-            final String word = mSuggestedWords.getWord(index);
-            mListener.pickSuggestionManually(index, word);
+            final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
+            mListener.pickSuggestionManually(index, wordInfo);
             dismissMoreSuggestions();
             return true;
         }
@@ -807,8 +808,8 @@
         if (index >= mSuggestedWords.size())
             return;
 
-        final String word = mSuggestedWords.getWord(index);
-        mListener.pickSuggestionManually(index, word);
+        final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
+        mListener.pickSuggestionManually(index, wordInfo);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java b/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
index c5f0959..4f86526 100644
--- a/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
+++ b/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
@@ -25,9 +25,10 @@
  */
 public final class BootBroadcastReceiver extends BroadcastReceiver {
     @Override
-    public void onReceive(Context context, Intent intent) {
+    public void onReceive(final Context context, final Intent intent) {
         if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
-            ResearchLogger.scheduleUploadingService(context);
+            UploaderService.cancelAndRescheduleUploadingService(context,
+                    true /* needsRescheduling */);
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index a38a226..e0bd37c 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -20,16 +20,13 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.app.AlarmManager;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.app.PendingIntent;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
@@ -74,22 +71,16 @@
 import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.research.MotionEventReader.ReplayData;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
 import java.nio.charset.Charset;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
-import java.util.Locale;
 import java.util.Random;
-import java.util.UUID;
 
 /**
  * Logs the use of the LatinIME keyboard.
@@ -254,7 +245,8 @@
         mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
         mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true);
         if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            scheduleUploadingService(mLatinIME);
+            UploaderService.cancelAndRescheduleUploadingService(mLatinIME,
+                    true /* needsRescheduling */);
         }
         mReplayer.setKeyboardSwitcher(keyboardSwitcher);
     }
@@ -268,25 +260,6 @@
         ResearchSettings.writeResearchLastDirCleanupTime(mPrefs, now);
     }
 
-    /**
-     * Arrange for the UploaderService to be run on a regular basis.
-     *
-     * Any existing scheduled invocation of UploaderService is removed and rescheduled.  This may
-     * cause problems if this method is called often and frequent updates are required, but since
-     * the user will likely be sleeping at some point, if the interval is less that the expected
-     * sleep duration and this method is not called during that time, the service should be invoked
-     * at some point.
-     */
-    public static void scheduleUploadingService(Context context) {
-        final Intent intent = new Intent(context, UploaderService.class);
-        final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
-        final AlarmManager manager =
-                (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-        manager.cancel(pendingIntent);
-        manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                UploaderService.RUN_INTERVAL, UploaderService.RUN_INTERVAL, pendingIntent);
-    }
-
     public void mainKeyboardView_onAttachedToWindow(final MainKeyboardView mainKeyboardView) {
         mMainKeyboardView = mainKeyboardView;
         maybeShowSplashScreen();
@@ -790,8 +763,7 @@
     }
 
     private boolean isAllowedToLog() {
-        return !mIsPasswordView && !mIsLoggingSuspended && sIsLogging && !mInFeedbackDialog
-                && !isReplaying();
+        return !mIsPasswordView && !mIsLoggingSuspended && sIsLogging && !mInFeedbackDialog;
     }
 
     public void requestIndicatorRedraw() {
@@ -1122,10 +1094,6 @@
         }
     }
 
-    public void latinIME_onFinishInputViewInternal() {
-        stop();
-    }
-
     /**
      * Log a change in preferences.
      *
@@ -1208,16 +1176,22 @@
     }
 
     /**
-     * Log a call to LatinIME.onWindowHidden().
+     * The IME is finishing; it is either being destroyed, or is about to be hidden.
      *
      * UserAction: The user has performed an action that has caused the IME to be closed.  They may
      * have focused on something other than a text field, or explicitly closed it.
      */
-    private static final LogStatement LOGSTATEMENT_LATINIME_ONWINDOWHIDDEN =
-            new LogStatement("LatinIMEOnWindowHidden", false, false, "isTextTruncated", "text");
-    public static void latinIME_onWindowHidden(final int savedSelectionStart,
-            final int savedSelectionEnd, final InputConnection ic) {
-        if (ic != null) {
+    private static final LogStatement LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL =
+            new LogStatement("LatinIMEOnFinishInputViewInternal", false, false, "isTextTruncated",
+                    "text");
+    public static void latinIME_onFinishInputViewInternal(final boolean finishingInput,
+            final int savedSelectionStart, final int savedSelectionEnd, final InputConnection ic) {
+        // The finishingInput flag is set in InputMethodService.  It is true if called from
+        // doFinishInput(), which can be called as part of doStartInput().  This can happen at times
+        // when the IME is not closing, such as when powering up.  The finishinInput flag is false
+        // if called from finishViews(), which is called from hideWindow() and onDestroy().  These
+        // are the situations in which we want to finish up the researchLog.
+        if (ic != null && !finishingInput) {
             final boolean isTextTruncated;
             final String text;
             if (LOG_FULL_TEXTVIEW_CONTENTS) {
@@ -1261,8 +1235,8 @@
             // Assume that OUTPUT_ENTIRE_BUFFER is only true when we don't care about privacy (e.g.
             // during a live user test), so the normal isPotentiallyPrivate and
             // isPotentiallyRevealing flags do not apply
-            researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONWINDOWHIDDEN, isTextTruncated,
-                    text);
+            researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL,
+                    isTextTruncated, text);
             researchLogger.commitCurrentLogUnit();
             getInstance().stop();
         }
@@ -1634,8 +1608,7 @@
         final String scrubbedAutoCorrection = scrubDigitsFromString(autoCorrection);
         final ResearchLogger researchLogger = getInstance();
         researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
-        researchLogger.commitCurrentLogUnitAsWord(scrubbedAutoCorrection, Long.MAX_VALUE,
-                isBatchMode);
+        researchLogger.onWordFinished(scrubbedAutoCorrection, isBatchMode);
 
         // Add the autocorrection logStatement at the end of the logUnit for the committed word.
         // We have to do this after calling commitCurrentLogUnitAsWord, because it may split the
diff --git a/java/src/com/android/inputmethod/research/UploaderService.java b/java/src/com/android/inputmethod/research/UploaderService.java
index 6a9f5c1..6a9717b 100644
--- a/java/src/com/android/inputmethod/research/UploaderService.java
+++ b/java/src/com/android/inputmethod/research/UploaderService.java
@@ -18,6 +18,8 @@
 
 import android.app.AlarmManager;
 import android.app.IntentService;
+import android.app.PendingIntent;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 
@@ -43,11 +45,17 @@
 
     @Override
     protected void onHandleIntent(final Intent intent) {
+        // We may reach this point either because the alarm fired, or because the system explicitly
+        // requested that an Upload occur.  In the latter case, we want to cancel the alarm in case
+        // it's about to fire.
+        cancelAndRescheduleUploadingService(this, false /* needsRescheduling */);
+
         final Uploader uploader = new Uploader(this);
         if (!uploader.isPossibleToUpload()) return;
         if (isUploadingUnconditionally(intent.getExtras()) || uploader.isConvenientToUpload()) {
             uploader.doUpload();
         }
+        cancelAndRescheduleUploadingService(this, true /* needsRescheduling */);
     }
 
     private boolean isUploadingUnconditionally(final Bundle bundle) {
@@ -57,4 +65,42 @@
         }
         return false;
     }
+
+    /**
+     * Arrange for the UploaderService to be run on a regular basis.
+     *
+     * Any existing scheduled invocation of UploaderService is removed and optionally rescheduled.
+     * This may cause problems if this method is called so often that no scheduled invocation is
+     * ever run.  But if the delay is short enough that it will go off when the user is sleeping,
+     * then there should be no starvation.
+     *
+     * @param context {@link Context} object
+     * @param needsRescheduling whether to schedule a future intent to be delivered to this service
+     */
+    public static void cancelAndRescheduleUploadingService(final Context context,
+            final boolean needsRescheduling) {
+        final PendingIntent pendingIntent = getPendingIntentForService(context);
+        final AlarmManager alarmManager = (AlarmManager) context.getSystemService(
+                Context.ALARM_SERVICE);
+        cancelAnyScheduledServiceAlarm(alarmManager, pendingIntent);
+        if (needsRescheduling) {
+            scheduleServiceAlarm(alarmManager, pendingIntent);
+        }
+    }
+
+    private static PendingIntent getPendingIntentForService(final Context context) {
+        final Intent intent = new Intent(context, UploaderService.class);
+        return PendingIntent.getService(context, 0, intent, 0);
+    }
+
+    private static void cancelAnyScheduledServiceAlarm(final AlarmManager alarmManager,
+            final PendingIntent pendingIntent) {
+        alarmManager.cancel(pendingIntent);
+    }
+
+    private static void scheduleServiceAlarm(final AlarmManager alarmManager,
+            final PendingIntent pendingIntent) {
+        alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, UploaderService.RUN_INTERVAL,
+                pendingIntent);
+    }
 }
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index 3735ec0..cbe9515 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -24,15 +24,14 @@
 include $(CLEAR_VARS)
 
 LATIN_IME_SRC_DIR := src
-LATIN_IME_SRC_FULLPATH_DIR := $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
 
-LOCAL_C_INCLUDES += $(LATIN_IME_SRC_FULLPATH_DIR) $(LATIN_IME_SRC_FULLPATH_DIR)/suggest
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
 
 LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-align \
     -Wwrite-strings -Wfloat-equal -Wpointer-arith -Winit-self -Wredundant-decls -Wno-system-headers
 
 ifeq ($(TARGET_ARCH), arm)
-ifneq ($(TARGET_GCC_VERSION), 4.7)
+ifeq ($(TARGET_GCC_VERSION), 4.6)
 LOCAL_CFLAGS += -Winline
 endif # TARGET_GCC_VERSION
 endif # TARGET_ARCH
@@ -53,14 +52,27 @@
     correction.cpp \
     dictionary.cpp \
     dic_traverse_wrapper.cpp \
+    digraph_utils.cpp \
     proximity_info.cpp \
     proximity_info_params.cpp \
     proximity_info_state.cpp \
     proximity_info_state_utils.cpp \
     unigram_dictionary.cpp \
     words_priority_queue.cpp \
-    suggest/gesture_suggest.cpp \
-    suggest/typing_suggest.cpp
+    suggest/core/suggest.cpp \
+    $(addprefix suggest/core/dicnode/, \
+        dic_node.cpp \
+        dic_node_utils.cpp \
+        dic_nodes_cache.cpp) \
+    suggest/core/policy/weighting.cpp \
+    suggest/core/session/dic_traverse_session.cpp \
+    suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
+    $(addprefix suggest/policyimpl/typing/, \
+        scoring_params.cpp \
+        typing_scoring.cpp \
+        typing_suggest_policy.cpp \
+        typing_traversal.cpp \
+        typing_weighting.cpp)
 
 LOCAL_SRC_FILES := \
     $(LATIN_IME_JNI_SRC_FILES) \
@@ -115,6 +127,4 @@
 #################### Clean up the tmp vars
 LATIN_IME_CORE_SRC_FILES :=
 LATIN_IME_JNI_SRC_FILES :=
-LATIN_IME_GESTURE_IMPL_SRC_FILES :=
 LATIN_IME_SRC_DIR :=
-LATIN_IME_SRC_FULLPATH_DIR :=
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index 30ca3f1..3c482ca 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -43,9 +43,12 @@
 }
 
 static JNINativeMethod sMethods[] = {
-    {"setProximityInfoNative", "(Ljava/lang/String;IIIII[II[I[I[I[I[I[F[F[F)J",
-            reinterpret_cast<void *>(latinime_Keyboard_setProximityInfo)},
-    {"releaseProximityInfoNative", "(J)V", reinterpret_cast<void *>(latinime_Keyboard_release)}
+    {const_cast<char *>("setProximityInfoNative"),
+     const_cast<char *>("(Ljava/lang/String;IIIII[II[I[I[I[I[I[F[F[F)J"),
+     reinterpret_cast<void *>(latinime_Keyboard_setProximityInfo)},
+    {const_cast<char *>("releaseProximityInfoNative"),
+     const_cast<char *>("(J)V"),
+     reinterpret_cast<void *>(latinime_Keyboard_release)}
 };
 
 int register_ProximityInfo(JNIEnv *env) {
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 9321c4b..11fa3da 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -280,19 +280,27 @@
 }
 
 static JNINativeMethod sMethods[] = {
-    {"openNative", "(Ljava/lang/String;JJ)J",
-            reinterpret_cast<void *>(latinime_BinaryDictionary_open)},
-    {"closeNative", "(J)V", reinterpret_cast<void *>(latinime_BinaryDictionary_close)},
-    {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[I[I[I[I)I",
-            reinterpret_cast<void *>(latinime_BinaryDictionary_getSuggestions)},
-    {"getProbabilityNative", "(J[I)I",
-            reinterpret_cast<void *>(latinime_BinaryDictionary_getProbability)},
-    {"isValidBigramNative", "(J[I[I)Z",
-            reinterpret_cast<void *>(latinime_BinaryDictionary_isValidBigram)},
-    {"calcNormalizedScoreNative", "([I[II)F",
-            reinterpret_cast<void *>(latinime_BinaryDictionary_calcNormalizedScore)},
-    {"editDistanceNative", "([I[I)I",
-            reinterpret_cast<void *>(latinime_BinaryDictionary_editDistance)}
+    {const_cast<char *>("openNative"),
+     const_cast<char *>("(Ljava/lang/String;JJ)J"),
+     reinterpret_cast<void *>(latinime_BinaryDictionary_open)},
+    {const_cast<char *>("closeNative"),
+     const_cast<char *>("(J)V"),
+     reinterpret_cast<void *>(latinime_BinaryDictionary_close)},
+    {const_cast<char *>("getSuggestionsNative"),
+     const_cast<char *>("(JJJ[I[I[I[I[IIIZ[IZ[I[I[I[I)I"),
+     reinterpret_cast<void *>(latinime_BinaryDictionary_getSuggestions)},
+    {const_cast<char *>("getProbabilityNative"),
+     const_cast<char *>("(J[I)I"),
+     reinterpret_cast<void *>(latinime_BinaryDictionary_getProbability)},
+    {const_cast<char *>("isValidBigramNative"),
+     const_cast<char *>("(J[I[I)Z"),
+     reinterpret_cast<void *>(latinime_BinaryDictionary_isValidBigram)},
+    {const_cast<char *>("calcNormalizedScoreNative"),
+     const_cast<char *>("([I[II)F"),
+     reinterpret_cast<void *>(latinime_BinaryDictionary_calcNormalizedScore)},
+    {const_cast<char *>("editDistanceNative"),
+     const_cast<char *>("([I[I)I"),
+     reinterpret_cast<void *>(latinime_BinaryDictionary_editDistance)}
 };
 
 int register_BinaryDictionary(JNIEnv *env) {
diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
index 9b39245..dfe3b09 100644
--- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
+++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
@@ -48,12 +48,15 @@
 }
 
 static JNINativeMethod sMethods[] = {
-    {"setDicTraverseSessionNative", "(Ljava/lang/String;)J",
-            reinterpret_cast<void *>(latinime_setDicTraverseSession)},
-    {"initDicTraverseSessionNative", "(JJ[II)V",
-            reinterpret_cast<void *>(latinime_initDicTraverseSession)},
-    {"releaseDicTraverseSessionNative", "(J)V",
-            reinterpret_cast<void *>(latinime_releaseDicTraverseSession)}
+    {const_cast<char *>("setDicTraverseSessionNative"),
+     const_cast<char *>("(Ljava/lang/String;)J"),
+     reinterpret_cast<void *>(latinime_setDicTraverseSession)},
+    {const_cast<char *>("initDicTraverseSessionNative"),
+     const_cast<char *>("(JJ[II)V"),
+     reinterpret_cast<void *>(latinime_initDicTraverseSession)},
+    {const_cast<char *>("releaseDicTraverseSessionNative"),
+     const_cast<char *>("(J)V"),
+     reinterpret_cast<void *>(latinime_releaseDicTraverseSession)}
 };
 
 int register_DicTraverseSession(JNIEnv *env) {
diff --git a/native/jni/jni_common.cpp b/native/jni/jni_common.cpp
index 1ea2041..8e5c508 100644
--- a/native/jni/jni_common.cpp
+++ b/native/jni/jni_common.cpp
@@ -16,12 +16,12 @@
 
 #define LOG_TAG "LatinIME: jni"
 
+#include "jni_common.h"
+
 #include "com_android_inputmethod_keyboard_ProximityInfo.h"
 #include "com_android_inputmethod_latin_BinaryDictionary.h"
 #include "com_android_inputmethod_latin_DicTraverseSession.h"
 #include "defines.h"
-#include "jni.h"
-#include "jni_common.h"
 
 /*
  * Returns the JNI version on success, -1 on failure.
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index 43e59a2..9289038 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -39,7 +39,7 @@
 void BigramDictionary::addWordBigram(int *word, int length, int probability, int *bigramProbability,
         int *bigramCodePoints, int *outputTypes) const {
     word[length] = 0;
-    if (DEBUG_DICT) {
+    if (DEBUG_DICT_FULL) {
 #ifdef FLAG_DBG
         char s[length + 1];
         for (int i = 0; i <= length; i++) s[i] = static_cast<char>(word[i]);
@@ -57,7 +57,7 @@
         }
         insertAt++;
     }
-    if (DEBUG_DICT) {
+    if (DEBUG_DICT_FULL) {
         AKLOGI("Bigram: InsertAt -> %d MAX_RESULTS: %d", insertAt, MAX_RESULTS);
     }
     if (insertAt >= MAX_RESULTS) {
@@ -76,7 +76,7 @@
         *dest++ = *word++;
     }
     *dest = 0; // NULL terminate
-    if (DEBUG_DICT) {
+    if (DEBUG_DICT_FULL) {
         AKLOGI("Bigram: Added word at %d", insertAt);
     }
 }
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 671507e..76234f8 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -954,7 +954,13 @@
 
 
 // In dictionary.cpp, getSuggestion() method,
-// suggestion scores are computed using the below formula.
+// When USE_SUGGEST_INTERFACE_FOR_TYPING is true:
+//   SUGGEST_INTERFACE_OUTPUT_SCALE was multiplied to the original suggestion scores to convert
+//   them to integers.
+//     score = (int)((original score) * SUGGEST_INTERFACE_OUTPUT_SCALE)
+//   Undo the scaling here to recover the original score.
+//     normalizedScore = ((float)score) / SUGGEST_INTERFACE_OUTPUT_SCALE
+// Otherwise: suggestion scores are computed using the below formula.
 // original score
 //  := powf(mTypedLetterMultiplier (this is defined 2),
 //         (the number of matched characters between typed word and suggested word))
@@ -991,16 +997,20 @@
         return 0.0f;
     }
 
+    // add a weight based on edit distance.
+    // distance <= max(afterLength, beforeLength) == afterLength,
+    // so, 0 <= distance / afterLength <= 1
+    const float weight = 1.0f - static_cast<float>(distance) / static_cast<float>(afterLength);
+
+    if (USE_SUGGEST_INTERFACE_FOR_TYPING) {
+        return (static_cast<float>(score) / SUGGEST_INTERFACE_OUTPUT_SCALE) * weight;
+    }
     const float maxScore = score >= S_INT_MAX ? static_cast<float>(S_INT_MAX)
             : static_cast<float>(MAX_INITIAL_SCORE)
                     * powf(static_cast<float>(TYPED_LETTER_MULTIPLIER),
                             static_cast<float>(min(beforeLength, afterLength - spaceCount)))
                     * static_cast<float>(FULL_WORD_MULTIPLIER);
 
-    // add a weight based on edit distance.
-    // distance <= max(afterLength, beforeLength) == afterLength,
-    // so, 0 <= distance / afterLength <= 1
-    const float weight = 1.0f - static_cast<float>(distance) / static_cast<float>(afterLength);
     return (static_cast<float>(score) / maxScore) * weight;
 }
 } // namespace latinime
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index f0d6210..a9e9b48 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -307,7 +307,7 @@
     mNeedsToTraverseAllNodes = true;
 }
 
-inline bool Correction::isSingleQuote(const int c) {
+AK_FORCE_INLINE bool Correction::isSingleQuote(const int c) {
     const int userTypedChar = mProximityInfoState.getPrimaryCodePointAt(mInputIndex);
     return (c == KEYCODE_SINGLE_QUOTE && userTypedChar != KEYCODE_SINGLE_QUOTE);
 }
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 6e09815..a456912 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -287,6 +287,7 @@
 
 #define CALIBRATE_SCORE_BY_TOUCH_COORDINATES true
 #define SUGGEST_MULTIPLE_WORDS true
+#define USE_SUGGEST_INTERFACE_FOR_TYPING true
 #define SUGGEST_INTERFACE_OUTPUT_SCALE 1000000.0f
 
 // The following "rate"s are used as a multiplier before dividing by 100, so they are in percent.
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index 6deab36..c998c06 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -16,14 +16,18 @@
 
 #define LOG_TAG "LatinIME: dictionary.cpp"
 
+#include "dictionary.h"
+
+#include <map> // TODO: remove
 #include <stdint.h>
 
 #include "bigram_dictionary.h"
 #include "binary_format.h"
 #include "defines.h"
-#include "dictionary.h"
 #include "dic_traverse_wrapper.h"
-#include "gesture_suggest.h"
+#include "suggest/core/suggest.h"
+#include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
+#include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
 #include "unigram_dictionary.h"
 
 namespace latinime {
@@ -34,13 +38,15 @@
           mDictSize(dictSize), mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust),
           mUnigramDictionary(new UnigramDictionary(mOffsetDict, BinaryFormat::getFlags(mDict))),
           mBigramDictionary(new BigramDictionary(mOffsetDict)),
-          mGestureSuggest(new GestureSuggest()) {
+          mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
+          mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
 }
 
 Dictionary::~Dictionary() {
     delete mUnigramDictionary;
     delete mBigramDictionary;
     delete mGestureSuggest;
+    delete mTypingSuggest;
 }
 
 int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession,
@@ -60,14 +66,26 @@
         }
         return result;
     } else {
-        std::map<int, int> bigramMap;
-        uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE];
-        mBigramDictionary->fillBigramAddressToProbabilityMapAndFilter(prevWordCodePoints,
-                prevWordLength, &bigramMap, bigramFilter);
-        result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
-                inputCodePoints, inputSize, &bigramMap, bigramFilter, useFullEditDistance, outWords,
-                frequencies, outputTypes);
-        return result;
+        if (USE_SUGGEST_INTERFACE_FOR_TYPING) {
+            DicTraverseWrapper::initDicTraverseSession(
+                    traverseSession, this, prevWordCodePoints, prevWordLength);
+            result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
+                    ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
+                    outWords, frequencies, spaceIndices, outputTypes);
+            if (DEBUG_DICT) {
+                DUMP_RESULT(outWords, frequencies);
+            }
+            return result;
+        } else {
+            std::map<int, int> bigramMap;
+            uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE];
+            mBigramDictionary->fillBigramAddressToProbabilityMapAndFilter(prevWordCodePoints,
+                    prevWordLength, &bigramMap, bigramFilter);
+            result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
+                    inputCodePoints, inputSize, &bigramMap, bigramFilter, useFullEditDistance,
+                    outWords, frequencies, outputTypes);
+            return result;
+        }
     }
 }
 
@@ -85,4 +103,9 @@
 bool Dictionary::isValidBigram(const int *word1, int length1, const int *word2, int length2) const {
     return mBigramDictionary->isValidBigram(word1, length1, word2, length2);
 }
+
+int Dictionary::getDictFlags() const {
+    return mUnigramDictionary->getDictFlags();
+}
+
 } // namespace latinime
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index 449b95a..0653d3c 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -63,6 +63,7 @@
     int getDictSize() const { return mDictSize; }
     int getMmapFd() const { return mMmapFd; }
     int getDictBufAdjust() const { return mDictBufAdjust; }
+    int getDictFlags() const;
     virtual ~Dictionary();
 
  private:
@@ -79,6 +80,7 @@
     const UnigramDictionary *mUnigramDictionary;
     const BigramDictionary *mBigramDictionary;
     SuggestInterface *mGestureSuggest;
+    SuggestInterface *mTypingSuggest;
 };
 } // namespace latinime
 #endif // LATINIME_DICTIONARY_H
diff --git a/native/jni/src/digraph_utils.cpp b/native/jni/src/digraph_utils.cpp
new file mode 100644
index 0000000..8781c50
--- /dev/null
+++ b/native/jni/src/digraph_utils.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "binary_format.h"
+#include "defines.h"
+#include "digraph_utils.h"
+
+namespace latinime {
+
+const DigraphUtils::digraph_t DigraphUtils::GERMAN_UMLAUT_DIGRAPHS[] =
+        { { 'a', 'e', 0x00E4 }, // U+00E4 : LATIN SMALL LETTER A WITH DIAERESIS
+        { 'o', 'e', 0x00F6 },   // U+00F6 : LATIN SMALL LETTER O WITH DIAERESIS
+        { 'u', 'e', 0x00FC } }; // U+00FC : LATIN SMALL LETTER U WITH DIAERESIS
+const DigraphUtils::digraph_t DigraphUtils::FRENCH_LIGATURES_DIGRAPHS[] =
+        { { 'a', 'e', 0x00E6 }, // U+00E6 : LATIN SMALL LETTER AE
+        { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE
+
+/* static */ bool DigraphUtils::hasDigraphForCodePoint(
+        const int dictFlags, const int compositeGlyphCodePoint) {
+    if (DigraphUtils::getDigraphForCodePoint(dictFlags, compositeGlyphCodePoint)) {
+        return true;
+    }
+    return false;
+}
+
+// Retrieves the set of all digraphs associated with the given dictionary.
+// Returns the size of the digraph array, or 0 if none exist.
+/* static */ int DigraphUtils::getAllDigraphsForDictionaryAndReturnSize(
+        const int dictFlags, const DigraphUtils::digraph_t **digraphs) {
+    if (BinaryFormat::REQUIRES_GERMAN_UMLAUT_PROCESSING & dictFlags) {
+        *digraphs = DigraphUtils::GERMAN_UMLAUT_DIGRAPHS;
+        return NELEMS(DigraphUtils::GERMAN_UMLAUT_DIGRAPHS);
+    }
+    if (BinaryFormat::REQUIRES_FRENCH_LIGATURES_PROCESSING & dictFlags) {
+        *digraphs = DigraphUtils::FRENCH_LIGATURES_DIGRAPHS;
+        return NELEMS(DigraphUtils::FRENCH_LIGATURES_DIGRAPHS);
+    }
+    return 0;
+}
+
+// Returns the digraph codepoint for the given composite glyph codepoint and digraph codepoint index
+// (which specifies the first or second codepoint in the digraph).
+/* static */ int DigraphUtils::getDigraphCodePointForIndex(const int dictFlags,
+        const int compositeGlyphCodePoint, const DigraphCodePointIndex digraphCodePointIndex) {
+    if (digraphCodePointIndex == NOT_A_DIGRAPH_INDEX) {
+        return NOT_A_CODE_POINT;
+    }
+    const DigraphUtils::digraph_t *digraph =
+            DigraphUtils::getDigraphForCodePoint(dictFlags, compositeGlyphCodePoint);
+    if (!digraph) {
+        return NOT_A_CODE_POINT;
+    }
+    if (digraphCodePointIndex == FIRST_DIGRAPH_CODEPOINT) {
+        return digraph->first;
+    } else if (digraphCodePointIndex == SECOND_DIGRAPH_CODEPOINT) {
+        return digraph->second;
+    }
+    ASSERT(false);
+    return NOT_A_CODE_POINT;
+}
+
+/**
+ * Returns the digraph for the input composite glyph codepoint, or 0 if none exists.
+ * dictFlags: the dictionary flags needed to determine which digraphs are supported.
+ * compositeGlyphCodePoint: the method returns the digraph corresponding to this codepoint.
+ */
+/* static */ const DigraphUtils::digraph_t *DigraphUtils::getDigraphForCodePoint(
+        const int dictFlags, const int compositeGlyphCodePoint) {
+    const DigraphUtils::digraph_t *digraphs = 0;
+    const int digraphsSize =
+            DigraphUtils::getAllDigraphsForDictionaryAndReturnSize(dictFlags, &digraphs);
+    for (int i = 0; i < digraphsSize; i++) {
+        if (digraphs[i].compositeGlyph == compositeGlyphCodePoint) {
+            return &digraphs[i];
+        }
+    }
+    return 0;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/digraph_utils.h b/native/jni/src/digraph_utils.h
new file mode 100644
index 0000000..6e364b6
--- /dev/null
+++ b/native/jni/src/digraph_utils.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DIGRAPH_UTILS_H
+#define DIGRAPH_UTILS_H
+
+namespace latinime {
+
+class DigraphUtils {
+ public:
+    typedef enum {
+        NOT_A_DIGRAPH_INDEX,
+        FIRST_DIGRAPH_CODEPOINT,
+        SECOND_DIGRAPH_CODEPOINT
+    } DigraphCodePointIndex;
+
+    typedef struct { int first; int second; int compositeGlyph; } digraph_t;
+
+    static bool hasDigraphForCodePoint(const int dictFlags, const int compositeGlyphCodePoint);
+    static int getAllDigraphsForDictionaryAndReturnSize(
+            const int dictFlags, const digraph_t **digraphs);
+    static int getDigraphCodePointForIndex(const int dictFlags, const int compositeGlyphCodePoint,
+            const DigraphCodePointIndex digraphCodePointIndex);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DigraphUtils);
+    static const digraph_t *getDigraphForCodePoint(
+            const int dictFlags, const int compositeGlyphCodePoint);
+
+    static const digraph_t GERMAN_UMLAUT_DIGRAPHS[];
+    static const digraph_t FRENCH_LIGATURES_DIGRAPHS[];
+};
+} // namespace latinime
+#endif // DIGRAPH_UTILS_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index 74b5e01..50f38e8 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -129,7 +129,7 @@
 }
 
 float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
-        const int keyId, const int x, const int y) const {
+        const int keyId, const int x, const int y, const float verticalScale) const {
     const bool correctTouchPosition = hasTouchPositionCorrectionData();
     const float centerX = static_cast<float>(correctTouchPosition ? getSweetSpotCenterXAt(keyId)
             : getKeyCenterXOfKeyIdG(keyId));
@@ -138,7 +138,7 @@
     if (correctTouchPosition) {
         const float sweetSpotCenterY = static_cast<float>(getSweetSpotCenterYAt(keyId));
         const float gapY = sweetSpotCenterY - visualKeyCenterY;
-        centerY = visualKeyCenterY + gapY * ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G;
+        centerY = visualKeyCenterY + gapY * verticalScale;
     } else {
         centerY = visualKeyCenterY;
     }
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index 57a175d..e21262f 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -39,7 +39,8 @@
     bool hasSpaceProximity(const int x, const int y) const;
     int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const;
     float getNormalizedSquaredDistanceFromCenterFloatG(
-            const int keyId, const int x, const int y) const;
+            const int keyId, const int x, const int y,
+            const float verticalScale) const;
     bool sameAsTyped(const unsigned short *word, int length) const;
     int getCodePointOf(const int keyIndex) const;
     bool hasSweetSpotData(const int keyIndex) const {
diff --git a/native/jni/src/proximity_info_params.cpp b/native/jni/src/proximity_info_params.cpp
index f9a4352..2675d9e 100644
--- a/native/jni/src/proximity_info_params.cpp
+++ b/native/jni/src/proximity_info_params.cpp
@@ -20,7 +20,8 @@
 namespace latinime {
 const float ProximityInfoParams::NOT_A_DISTANCE_FLOAT = -1.0f;
 const int ProximityInfoParams::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE = 5;
-const float ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G = 1.1f;
+const float ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE = 1.0f;
+const float ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G = 0.5f;
 
 /* Per method constants */
 // Used by ProximityInfoStateUtils::initGeometricDistanceInfos()
diff --git a/native/jni/src/proximity_info_params.h b/native/jni/src/proximity_info_params.h
index e7aec09..4e47f73 100644
--- a/native/jni/src/proximity_info_params.h
+++ b/native/jni/src/proximity_info_params.h
@@ -25,6 +25,7 @@
  public:
     static const float NOT_A_DISTANCE_FLOAT;
     static const int MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE;
+    static const float VERTICAL_SWEET_SPOT_SCALE;
     static const float VERTICAL_SWEET_SPOT_SCALE_G;
 
     // Used by ProximityInfoStateUtils::initGeometricDistanceInfos()
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index 7fcfd5d..a10b260 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -28,16 +28,19 @@
 
 namespace latinime {
 
+// TODO: Remove the dependency of "isGeometric"
 void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
         const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
         const int *const xCoordinates, const int *const yCoordinates, const int *const times,
         const int *const pointerIds, const bool isGeometric) {
     ASSERT(isGeometric || (inputSize < MAX_WORD_LENGTH));
-    mIsContinuationPossible = ProximityInfoStateUtils::checkAndReturnIsContinuationPossible(
-            inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
-            &mSampledInputYs, &mSampledTimes, &mSampledInputIndice);
+    mIsContinuousSuggestionPossible =
+            ProximityInfoStateUtils::checkAndReturnIsContinuousSuggestionPossible(
+                    inputSize, xCoordinates, yCoordinates, times, mSampledInputSize,
+                    &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledInputIndice);
     if (DEBUG_DICT) {
-        AKLOGI("isContinuationPossible = %s", (mIsContinuationPossible ? "true" : "false"));
+        AKLOGI("isContinuousSuggestionPossible = %s",
+                (mIsContinuousSuggestionPossible ? "true" : "false"));
     }
 
     mProximityInfo = proximityInfo;
@@ -64,7 +67,7 @@
     mSampledInputSize = 0;
     mMostProbableStringProbability = 0.0f;
 
-    if (mIsContinuationPossible && mSampledInputIndice.size() > 1) {
+    if (mIsContinuousSuggestionPossible && mSampledInputIndice.size() > 1) {
         // Just update difference.
         // Previous two points are never skipped. Thus, we pop 2 input point data here.
         pushTouchPointStartIndex = ProximityInfoStateUtils::trimLastTwoTouchPoints(
@@ -92,12 +95,17 @@
                 pushTouchPointStartIndex, lastSavedInputSize);
     }
 
+    // TODO: Remove the dependency of "isGeometric"
+    const float verticalSweetSpotScale = isGeometric
+            ? ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G
+            : ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE;
+
     if (xCoordinates && yCoordinates) {
         mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(mProximityInfo,
                 mMaxPointToKeyLength, mInputProximities, xCoordinates, yCoordinates, times,
-                pointerIds, inputSize, isGeometric, pointerId, pushTouchPointStartIndex,
-                &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache,
-                &mSampledInputIndice);
+                pointerIds, verticalSweetSpotScale, inputSize, isGeometric, pointerId,
+                pushTouchPointStartIndex, &mSampledInputXs, &mSampledInputYs, &mSampledTimes,
+                &mSampledLengthCache, &mSampledInputIndice);
     }
 
     if (mSampledInputSize > 0 && isGeometric) {
@@ -113,8 +121,8 @@
 
     if (mSampledInputSize > 0) {
         ProximityInfoStateUtils::initGeometricDistanceInfos(mProximityInfo, mSampledInputSize,
-                lastSavedInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledNearKeySets,
-                &mSampledDistanceCache_G);
+                lastSavedInputSize, verticalSweetSpotScale, &mSampledInputXs, &mSampledInputYs,
+                &mSampledNearKeySets, &mSampledDistanceCache_G);
         if (isGeometric) {
             // updates probabilities of skipping or mapping each key for all points.
             ProximityInfoStateUtils::updateAlignPointProbabilities(
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
index 224240b..9bba751 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/proximity_info_state.h
@@ -47,12 +47,12 @@
             : mProximityInfo(0), mMaxPointToKeyLength(0.0f), mAverageSpeed(0.0f),
               mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0),
               mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
-              mIsContinuationPossible(false), mSampledInputXs(), mSampledInputYs(), mSampledTimes(),
-              mSampledInputIndice(), mSampledLengthCache(), mBeelineSpeedPercentiles(),
-              mSampledDistanceCache_G(), mSpeedRates(), mDirections(), mCharProbabilities(),
-              mSampledNearKeySets(), mSampledSearchKeySets(), mSampledSearchKeyVectors(),
-              mTouchPositionCorrectionEnabled(false), mSampledInputSize(0),
-              mMostProbableStringProbability(0.0f) {
+              mIsContinuousSuggestionPossible(false), mSampledInputXs(), mSampledInputYs(),
+              mSampledTimes(), mSampledInputIndice(), mSampledLengthCache(),
+              mBeelineSpeedPercentiles(), mSampledDistanceCache_G(), mSpeedRates(), mDirections(),
+              mCharProbabilities(), mSampledNearKeySets(), mSampledSearchKeySets(),
+              mSampledSearchKeyVectors(), mTouchPositionCorrectionEnabled(false),
+              mSampledInputSize(0), mMostProbableStringProbability(0.0f) {
         memset(mInputProximities, 0, sizeof(mInputProximities));
         memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
         memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
@@ -143,8 +143,8 @@
         return mSampledLengthCache[index];
     }
 
-    bool isContinuationPossible() const {
-        return mIsContinuationPossible;
+    bool isContinuousSuggestionPossible() const {
+        return mIsContinuousSuggestionPossible;
     }
 
     float getPointToKeyByIdLength(const int inputIndex, const int keyId) const;
@@ -223,7 +223,7 @@
     int mCellWidth;
     int mGridHeight;
     int mGridWidth;
-    bool mIsContinuationPossible;
+    bool mIsContinuousSuggestionPossible;
 
     std::vector<int> mSampledInputXs;
     std::vector<int> mSampledInputYs;
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/proximity_info_state_utils.cpp
index ccb28bc..df70cff 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/proximity_info_state_utils.cpp
@@ -42,8 +42,8 @@
         const ProximityInfo *const proximityInfo, const int maxPointToKeyLength,
         const int *const inputProximities, const int *const inputXCoordinates,
         const int *const inputYCoordinates, const int *const times, const int *const pointerIds,
-        const int inputSize, const bool isGeometric, const int pointerId,
-        const int pushTouchPointStartIndex, std::vector<int> *sampledInputXs,
+        const float verticalSweetSpotScale, const int inputSize, const bool isGeometric,
+        const int pointerId, const int pushTouchPointStartIndex, std::vector<int> *sampledInputXs,
         std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes,
         std::vector<int> *sampledLengthCache, std::vector<int> *sampledInputIndice) {
     if (DEBUG_SAMPLING_POINTS) {
@@ -112,10 +112,10 @@
             }
 
             if (pushTouchPoint(proximityInfo, maxPointToKeyLength, i, c, x, y, time,
-                    isGeometric /* doSampling */, i == lastInputIndex, sumAngle,
-                    currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances,
-                    sampledInputXs, sampledInputYs, sampledInputTimes, sampledLengthCache,
-                    sampledInputIndice)) {
+                    verticalSweetSpotScale, isGeometric /* doSampling */, i == lastInputIndex,
+                    sumAngle, currentNearKeysDistances, prevNearKeysDistances,
+                    prevPrevNearKeysDistances, sampledInputXs, sampledInputYs, sampledInputTimes,
+                    sampledLengthCache, sampledInputIndice)) {
                 // Previous point information was popped.
                 NearKeysDistanceMap *tmp = prevNearKeysDistances;
                 prevNearKeysDistances = currentNearKeysDistances;
@@ -222,7 +222,8 @@
 
 /* static */ void ProximityInfoStateUtils::initGeometricDistanceInfos(
         const ProximityInfo *const proximityInfo, const int sampledInputSize,
-        const int lastSavedInputSize, const std::vector<int> *const sampledInputXs,
+        const int lastSavedInputSize, const float verticalSweetSpotScale,
+        const std::vector<int> *const sampledInputXs,
         const std::vector<int> *const sampledInputYs,
         std::vector<NearKeycodesSet> *SampledNearKeySets,
         std::vector<float> *SampledDistanceCache_G) {
@@ -236,7 +237,8 @@
             const int x = (*sampledInputXs)[i];
             const int y = (*sampledInputYs)[i];
             const float normalizedSquaredDistance =
-                    proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y);
+                    proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(
+                            k, x, y, verticalSweetSpotScale);
             (*SampledDistanceCache_G)[index] = normalizedSquaredDistance;
             if (normalizedSquaredDistance
                     < ProximityInfoParams::NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD) {
@@ -354,12 +356,14 @@
 // the given point and the nearest key position.
 /* static */ float ProximityInfoStateUtils::updateNearKeysDistances(
         const ProximityInfo *const proximityInfo, const float maxPointToKeyLength, const int x,
-        const int y, NearKeysDistanceMap *const currentNearKeysDistances) {
+        const int y, const float verticalSweetspotScale,
+        NearKeysDistanceMap *const currentNearKeysDistances) {
     currentNearKeysDistances->clear();
     const int keyCount = proximityInfo->getKeyCount();
     float nearestKeyDistance = maxPointToKeyLength;
     for (int k = 0; k < keyCount; ++k) {
-        const float dist = proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y);
+        const float dist = proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y,
+                verticalSweetspotScale);
         if (dist < ProximityInfoParams::NEAR_KEY_THRESHOLD_FOR_DISTANCE) {
             currentNearKeysDistances->insert(std::pair<int, float>(k, dist));
         }
@@ -439,7 +443,8 @@
 // Returning if previous point is popped or not.
 /* static */ bool ProximityInfoStateUtils::pushTouchPoint(const ProximityInfo *const proximityInfo,
         const int maxPointToKeyLength, const int inputIndex, const int nodeCodePoint, int x, int y,
-        const int time, const bool doSampling, const bool isLastPoint, const float sumAngle,
+        const int time, const float verticalSweetSpotScale, const bool doSampling,
+        const bool isLastPoint, const float sumAngle,
         NearKeysDistanceMap *const currentNearKeysDistances,
         const NearKeysDistanceMap *const prevNearKeysDistances,
         const NearKeysDistanceMap *const prevPrevNearKeysDistances,
@@ -451,8 +456,8 @@
     size_t size = sampledInputXs->size();
     bool popped = false;
     if (nodeCodePoint < 0 && doSampling) {
-        const float nearest = updateNearKeysDistances(
-                proximityInfo, maxPointToKeyLength, x, y, currentNearKeysDistances);
+        const float nearest = updateNearKeysDistances(proximityInfo, maxPointToKeyLength, x, y,
+                verticalSweetSpotScale, currentNearKeysDistances);
         const float score = getPointScore(mostCommonKeyWidth, x, y, time, isLastPoint, nearest,
                 sumAngle, currentNearKeysDistances, prevNearKeysDistances,
                 prevPrevNearKeysDistances, sampledInputXs, sampledInputYs);
@@ -968,10 +973,10 @@
     return true;
 }
 
-/* static */ bool ProximityInfoStateUtils::checkAndReturnIsContinuationPossible(const int inputSize,
-        const int *const xCoordinates, const int *const yCoordinates, const int *const times,
-        const int sampledInputSize, const std::vector<int> *const sampledInputXs,
-        const std::vector<int> *const sampledInputYs,
+/* static */ bool ProximityInfoStateUtils::checkAndReturnIsContinuousSuggestionPossible(
+        const int inputSize, const int *const xCoordinates, const int *const yCoordinates,
+        const int *const times, const int sampledInputSize,
+        const std::vector<int> *const sampledInputXs, const std::vector<int> *const sampledInputYs,
         const std::vector<int> *const sampledTimes,
         const std::vector<int> *const sampledInputIndices) {
     if (inputSize < sampledInputSize) {
diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/proximity_info_state_utils.h
index a7f4a34..c9feb59 100644
--- a/native/jni/src/proximity_info_state_utils.h
+++ b/native/jni/src/proximity_info_state_utils.h
@@ -38,7 +38,8 @@
     static int updateTouchPoints(const ProximityInfo *const proximityInfo,
             const int maxPointToKeyLength, const int *const inputProximities,
             const int *const inputXCoordinates, const int *const inputYCoordinates,
-            const int *const times, const int *const pointerIds, const int inputSize,
+            const int *const times, const int *const pointerIds,
+            const float verticalSweetSpotScale, const int inputSize,
             const bool isGeometric, const int pointerId, const int pushTouchPointStartIndex,
             std::vector<int> *sampledInputXs, std::vector<int> *sampledInputYs,
             std::vector<int> *sampledInputTimes, std::vector<int> *sampledLengthCache,
@@ -84,6 +85,7 @@
             const int inputIndex, const int keyId);
     static void initGeometricDistanceInfos(const ProximityInfo *const proximityInfo,
             const int sampledInputSize, const int lastSavedInputSize,
+            const float verticalSweetSpotScale,
             const std::vector<int> *const sampledInputXs,
             const std::vector<int> *const sampledInputYs,
             std::vector<NearKeycodesSet> *SampledNearKeySets,
@@ -101,7 +103,7 @@
             const std::vector<int> *const sampledTimes,
             const std::vector<float> *const sampledSpeedRates,
             const std::vector<int> *const sampledBeelineSpeedPercentiles);
-    static bool checkAndReturnIsContinuationPossible(const int inputSize,
+    static bool checkAndReturnIsContinuousSuggestionPossible(const int inputSize,
             const int *const xCoordinates, const int *const yCoordinates, const int *const times,
             const int sampledInputSize, const std::vector<int> *const sampledInputXs,
             const std::vector<int> *const sampledInputYs,
@@ -118,6 +120,7 @@
 
     static float updateNearKeysDistances(const ProximityInfo *const proximityInfo,
             const float maxPointToKeyLength, const int x, const int y,
+            const float verticalSweetSpotScale,
             NearKeysDistanceMap *const currentNearKeysDistances);
     static bool isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances,
             const NearKeysDistanceMap *const prevNearKeysDistances,
@@ -130,7 +133,8 @@
             std::vector<int> *sampledInputXs, std::vector<int> *sampledInputYs);
     static bool pushTouchPoint(const ProximityInfo *const proximityInfo,
             const int maxPointToKeyLength, const int inputIndex, const int nodeCodePoint, int x,
-            int y, const int time, const bool doSampling, const bool isLastPoint,
+            int y, const int time, const float verticalSweetSpotScale,
+            const bool doSampling, const bool isLastPoint,
             const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances,
             const NearKeysDistanceMap *const prevNearKeysDistances,
             const NearKeysDistanceMap *const prevPrevNearKeysDistances,
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.cpp b/native/jni/src/suggest/core/dicnode/dic_node.cpp
new file mode 100644
index 0000000..8c48c58
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dic_node.h"
+
+namespace latinime {
+
+DicNode::DicNode(const DicNode &dicNode)
+        :
+#if DEBUG_DICT
+          mProfiler(dicNode.mProfiler),
+#endif
+          mDicNodeProperties(dicNode.mDicNodeProperties), mDicNodeState(dicNode.mDicNodeState),
+          mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion), mIsUsed(dicNode.mIsUsed),
+          mReleaseListener(0) {
+    /* empty */
+}
+
+DicNode &DicNode::operator=(const DicNode &dicNode) {
+#if DEBUG_DICT
+    mProfiler = dicNode.mProfiler;
+#endif
+    mDicNodeProperties = dicNode.mDicNodeProperties;
+    mDicNodeState = dicNode.mDicNodeState;
+    mIsCachedForNextSuggestion = dicNode.mIsCachedForNextSuggestion;
+    mIsUsed = dicNode.mIsUsed;
+    mReleaseListener = dicNode.mReleaseListener;
+    return *this;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
new file mode 100644
index 0000000..cde7b99
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_H
+#define LATINIME_DIC_NODE_H
+
+#include "char_utils.h"
+#include "defines.h"
+#include "dic_node_state.h"
+#include "dic_node_profiler.h"
+#include "dic_node_properties.h"
+#include "dic_node_release_listener.h"
+
+#if DEBUG_DICT
+#define LOGI_SHOW_ADD_COST_PROP \
+        do { char charBuf[50]; \
+        INTS_TO_CHARS(getOutputWordBuf(), getDepth(), charBuf); \
+        AKLOGI("%20s, \"%c\", size = %03d, total = %03d, index(0) = %02d, dist = %.4f, %s,,", \
+                __FUNCTION__, getNodeCodePoint(), inputSize, getTotalInputIndex(), \
+                getInputIndex(0), getNormalizedCompoundDistance(), charBuf); } while (0)
+#define DUMP_WORD_AND_SCORE(header) \
+        do { char charBuf[50]; char prevWordCharBuf[50]; \
+        INTS_TO_CHARS(getOutputWordBuf(), getDepth(), charBuf); \
+        INTS_TO_CHARS(mDicNodeState.mDicNodeStatePrevWord.mPrevWord, \
+                mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength(), prevWordCharBuf); \
+        AKLOGI("#%8s, %5f, %5f, %5f, %5f, %s, %s, %d,,", header, \
+                getSpatialDistanceForScoring(), getLanguageDistanceForScoring(), \
+                getNormalizedCompoundDistance(), getRawLength(), prevWordCharBuf, charBuf, \
+                getInputIndex(0)); \
+        } while (0)
+#else
+#define LOGI_SHOW_ADD_COST_PROP
+#define DUMP_WORD_AND_SCORE(header)
+#endif
+
+namespace latinime {
+
+// This struct is purely a bucket to return values. No instances of this struct should be kept.
+struct DicNode_InputStateG {
+    bool mNeedsToUpdateInputStateG;
+    int mPointerId;
+    int16_t mInputIndex;
+    int mPrevCodePoint;
+    float mTerminalDiffCost;
+    float mRawLength;
+    DoubleLetterLevel mDoubleLetterLevel;
+};
+
+class DicNode {
+    // Caveat: We define Weighting as a friend class of DicNode to let Weighting change
+    // the distance of DicNode.
+    // Caution!!! In general, we avoid using the "friend" access modifier.
+    // This is an exception to explicitly hide DicNode::addCost() from all classes but Weighting.
+    friend class Weighting;
+
+ public:
+#if DEBUG_DICT
+    DicNodeProfiler mProfiler;
+#endif
+    //////////////////
+    // Memory utils //
+    //////////////////
+    AK_FORCE_INLINE static void managedDelete(DicNode *node) {
+        node->remove();
+    }
+    // end
+    /////////////////
+
+    AK_FORCE_INLINE DicNode()
+            :
+#if DEBUG_DICT
+              mProfiler(),
+#endif
+              mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false),
+              mIsUsed(false), mReleaseListener(0) {}
+
+    DicNode(const DicNode &dicNode);
+    DicNode &operator=(const DicNode &dicNode);
+    virtual ~DicNode() {}
+
+    // TODO: minimize arguments by looking binary_format
+    // Init for copy
+    void initByCopy(const DicNode *dicNode) {
+        mIsUsed = true;
+        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
+        mDicNodeProperties.init(&dicNode->mDicNodeProperties);
+        mDicNodeState.init(&dicNode->mDicNodeState);
+        PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
+    }
+
+    // TODO: minimize arguments by looking binary_format
+    // Init for root with prevWordNodePos which is used for bigram
+    void initAsRoot(const int pos, const int childrenPos, const int childrenCount,
+            const int prevWordNodePos) {
+        mIsUsed = true;
+        mIsCachedForNextSuggestion = false;
+        mDicNodeProperties.init(
+                pos, 0, childrenPos, 0, 0, 0, childrenCount, 0, 0, false, false, true, 0, 0);
+        mDicNodeState.init(prevWordNodePos);
+        PROF_NODE_RESET(mProfiler);
+    }
+
+    void initAsPassingChild(DicNode *parentNode) {
+        mIsUsed = true;
+        mIsCachedForNextSuggestion = parentNode->mIsCachedForNextSuggestion;
+        const int c = parentNode->getNodeTypedCodePoint();
+        mDicNodeProperties.init(&parentNode->mDicNodeProperties, c);
+        mDicNodeState.init(&parentNode->mDicNodeState);
+        PROF_NODE_COPY(&parentNode->mProfiler, mProfiler);
+    }
+
+    // TODO: minimize arguments by looking binary_format
+    // Init for root with previous word
+    void initAsRootWithPreviousWord(DicNode *dicNode, const int pos, const int childrenPos,
+            const int childrenCount) {
+        mIsUsed = true;
+        mIsCachedForNextSuggestion = false;
+        mDicNodeProperties.init(
+                pos, 0, childrenPos, 0, 0, 0, childrenCount, 0, 0, false, false, true, 0, 0);
+        // TODO: Move to dicNodeState?
+        mDicNodeState.mDicNodeStateOutput.init(); // reset for next word
+        mDicNodeState.mDicNodeStateInput.init(
+                &dicNode->mDicNodeState.mDicNodeStateInput, true /* resetTerminalDiffCost */);
+        mDicNodeState.mDicNodeStateScoring.init(
+                &dicNode->mDicNodeState.mDicNodeStateScoring);
+        mDicNodeState.mDicNodeStatePrevWord.init(
+                dicNode->mDicNodeState.mDicNodeStatePrevWord.getPrevWordCount() + 1,
+                dicNode->mDicNodeProperties.getProbability(),
+                dicNode->mDicNodeProperties.getPos(),
+                dicNode->mDicNodeState.mDicNodeStatePrevWord.mPrevWord,
+                dicNode->mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength(),
+                dicNode->getOutputWordBuf(),
+                dicNode->mDicNodeProperties.getDepth(),
+                dicNode->mDicNodeState.mDicNodeStatePrevWord.mPrevSpacePositions,
+                mDicNodeState.mDicNodeStateInput.getInputIndex(0) /* lastInputIndex */);
+        PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
+    }
+
+    // TODO: minimize arguments by looking binary_format
+    void initAsChild(DicNode *dicNode, const int pos, const uint8_t flags, const int childrenPos,
+            const int attributesPos, const int siblingPos, const int nodeCodePoint,
+            const int childrenCount, const int probability, const int bigramProbability,
+            const bool isTerminal, const bool hasMultipleChars, const bool hasChildren,
+            const uint16_t additionalSubwordLength, const int *additionalSubword) {
+        mIsUsed = true;
+        uint16_t newDepth = static_cast<uint16_t>(dicNode->getDepth() + 1);
+        mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
+        const uint16_t newLeavingDepth = static_cast<uint16_t>(
+                dicNode->mDicNodeProperties.getLeavingDepth() + additionalSubwordLength);
+        mDicNodeProperties.init(pos, flags, childrenPos, attributesPos, siblingPos, nodeCodePoint,
+                childrenCount, probability, bigramProbability, isTerminal, hasMultipleChars,
+                hasChildren, newDepth, newLeavingDepth);
+        mDicNodeState.init(&dicNode->mDicNodeState, additionalSubwordLength, additionalSubword);
+        PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
+    }
+
+    AK_FORCE_INLINE void remove() {
+        mIsUsed = false;
+        if (mReleaseListener) {
+            mReleaseListener->onReleased(this);
+        }
+    }
+
+    bool isUsed() const {
+        return mIsUsed;
+    }
+
+    bool isRoot() const {
+        return getDepth() == 0;
+    }
+
+    bool hasChildren() const {
+        return mDicNodeProperties.hasChildren();
+    }
+
+    bool isLeavingNode() const {
+        ASSERT(getDepth() <= getLeavingDepth());
+        return getDepth() == getLeavingDepth();
+    }
+
+    AK_FORCE_INLINE bool isFirstLetter() const {
+        return getDepth() == 1;
+    }
+
+    bool isCached() const {
+        return mIsCachedForNextSuggestion;
+    }
+
+    void setCached() {
+        mIsCachedForNextSuggestion = true;
+    }
+
+    // Used to expand the node in DicNodeUtils
+    int getNodeTypedCodePoint() const {
+        return mDicNodeState.mDicNodeStateOutput.getCodePointAt(getDepth());
+    }
+
+    bool isImpossibleBigramWord() const {
+        const int probability = mDicNodeProperties.getProbability();
+        if (probability == 0) {
+            return true;
+        }
+        const int prevWordLen = mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength()
+                - mDicNodeState.mDicNodeStatePrevWord.getPrevWordStart() - 1;
+        const int currentWordLen = getDepth();
+        return (prevWordLen == 1 && currentWordLen == 1);
+    }
+
+    bool isCapitalized() const {
+        const int c = getOutputWordBuf()[0];
+        return isAsciiUpper(c);
+    }
+
+    bool isFirstWord() const {
+        return mDicNodeState.mDicNodeStatePrevWord.getPrevWordNodePos() == NOT_VALID_WORD;
+    }
+
+    bool isCompletion(const int inputSize) const {
+        return mDicNodeState.mDicNodeStateInput.getInputIndex(0) >= inputSize;
+    }
+
+    bool canDoLookAheadCorrection(const int inputSize) const {
+        return mDicNodeState.mDicNodeStateInput.getInputIndex(0) < inputSize - 1;
+    }
+
+    // Used to get bigram probability in DicNodeUtils
+    int getPos() const {
+        return mDicNodeProperties.getPos();
+    }
+
+    // Used to get bigram probability in DicNodeUtils
+    int getPrevWordPos() const {
+        return mDicNodeState.mDicNodeStatePrevWord.getPrevWordNodePos();
+    }
+
+    // Used in DicNodeUtils
+    int getChildrenPos() const {
+        return mDicNodeProperties.getChildrenPos();
+    }
+
+    // Used in DicNodeUtils
+    int getChildrenCount() const {
+        return mDicNodeProperties.getChildrenCount();
+    }
+
+    // Used in DicNodeUtils
+    int getProbability() const {
+        return mDicNodeProperties.getProbability();
+    }
+
+    AK_FORCE_INLINE bool isTerminalWordNode() const {
+        const bool isTerminalNodes = mDicNodeProperties.isTerminal();
+        const int currentNodeDepth = getDepth();
+        const int terminalNodeDepth = mDicNodeProperties.getLeavingDepth();
+        return isTerminalNodes && currentNodeDepth > 0 && currentNodeDepth == terminalNodeDepth;
+    }
+
+    bool shouldBeFilterdBySafetyNetForBigram() const {
+        const uint16_t currentDepth = getDepth();
+        const int prevWordLen = mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength()
+                - mDicNodeState.mDicNodeStatePrevWord.getPrevWordStart() - 1;
+        return !(currentDepth > 0 && (currentDepth != 1 || prevWordLen != 1));
+    }
+
+    uint16_t getLeavingDepth() const {
+        return mDicNodeProperties.getLeavingDepth();
+    }
+
+    bool isTotalInputSizeExceedingLimit() const {
+        const int prevWordsLen = mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength();
+        const int currentWordDepth = getDepth();
+        // TODO: 3 can be 2? Needs to be investigated.
+        // TODO: Have a const variable for 3 (or 2)
+        return prevWordsLen + currentWordDepth > MAX_WORD_LENGTH - 3;
+    }
+
+    // TODO: This may be defective. Needs to be revised.
+    bool truncateNode(const DicNode *const topNode, const int inputCommitPoint) {
+        const int prevWordLenOfTop = mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength();
+        int newPrevWordStartIndex = inputCommitPoint;
+        int charCount = 0;
+        // Find new word start index
+        for (int i = 0; i < prevWordLenOfTop; ++i) {
+            const int c = mDicNodeState.mDicNodeStatePrevWord.getPrevWordCodePointAt(i);
+            // TODO: Check other separators.
+            if (c != KEYCODE_SPACE && c != KEYCODE_SINGLE_QUOTE) {
+                if (charCount == inputCommitPoint) {
+                    newPrevWordStartIndex = i;
+                    break;
+                }
+                ++charCount;
+            }
+        }
+        if (!mDicNodeState.mDicNodeStatePrevWord.startsWith(
+                &topNode->mDicNodeState.mDicNodeStatePrevWord, newPrevWordStartIndex - 1)) {
+            // Node mismatch.
+            return false;
+        }
+        mDicNodeState.mDicNodeStateInput.truncate(inputCommitPoint);
+        mDicNodeState.mDicNodeStatePrevWord.truncate(newPrevWordStartIndex);
+        return true;
+    }
+
+    void outputResult(int *dest) const {
+        const uint16_t prevWordLength = mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength();
+        const uint16_t currentDepth = getDepth();
+        DicNodeUtils::appendTwoWords(mDicNodeState.mDicNodeStatePrevWord.mPrevWord,
+                   prevWordLength, getOutputWordBuf(), currentDepth, dest);
+        DUMP_WORD_AND_SCORE("OUTPUT");
+    }
+
+    void outputSpacePositionsResult(int *spaceIndices) const {
+        mDicNodeState.mDicNodeStatePrevWord.outputSpacePositions(spaceIndices);
+    }
+
+    bool hasMultipleWords() const {
+        return mDicNodeState.mDicNodeStatePrevWord.getPrevWordCount() > 0;
+    }
+
+    float getProximityCorrectionCount() const {
+        return static_cast<float>(mDicNodeState.mDicNodeStateScoring.getProximityCorrectionCount());
+    }
+
+    float getEditCorrectionCount() const {
+        return static_cast<float>(mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount());
+    }
+
+    // Used to prune nodes
+    float getNormalizedCompoundDistance() const {
+        return mDicNodeState.mDicNodeStateScoring.getNormalizedCompoundDistance();
+    }
+
+    // Used to prune nodes
+    float getNormalizedSpatialDistance() const {
+        return mDicNodeState.mDicNodeStateScoring.getSpatialDistance()
+                / static_cast<float>(getInputIndex(0) + 1);
+    }
+
+    // Used to prune nodes
+    float getCompoundDistance() const {
+        return mDicNodeState.mDicNodeStateScoring.getCompoundDistance();
+    }
+
+    // Used to prune nodes
+    float getCompoundDistance(const float languageWeight) const {
+        return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(languageWeight);
+    }
+
+    // Note that "cost" means delta for "distance" that is weighted.
+    float getTotalPrevWordsLanguageCost() const {
+        return mDicNodeState.mDicNodeStateScoring.getTotalPrevWordsLanguageCost();
+    }
+
+    // Used to commit input partially
+    int getPrevWordNodePos() const {
+        return mDicNodeState.mDicNodeStatePrevWord.getPrevWordNodePos();
+    }
+
+    AK_FORCE_INLINE const int *getOutputWordBuf() const {
+        return mDicNodeState.mDicNodeStateOutput.mWordBuf;
+    }
+
+    int getPrevCodePointG(int pointerId) const {
+        return mDicNodeState.mDicNodeStateInput.getPrevCodePoint(pointerId);
+    }
+
+    // Whether the current codepoint can be an intentional omission, in which case the traversal
+    // algorithm will always check for a possible omission here.
+    bool canBeIntentionalOmission() const {
+        return isIntentionalOmissionCodePoint(getNodeCodePoint());
+    }
+
+    // Whether the omission is so frequent that it should incur zero cost.
+    bool isZeroCostOmission() const {
+        // TODO: do not hardcode and read from header
+        return (getNodeCodePoint() == KEYCODE_SINGLE_QUOTE);
+    }
+
+    // TODO: remove
+    float getTerminalDiffCostG(int path) const {
+        return mDicNodeState.mDicNodeStateInput.getTerminalDiffCost(path);
+    }
+
+    //////////////////////
+    // Temporary getter //
+    // TODO: Remove     //
+    //////////////////////
+    // TODO: Remove once touch path is merged into ProximityInfoState
+    int getNodeCodePoint() const {
+        return mDicNodeProperties.getNodeCodePoint();
+    }
+
+    ////////////////////////////////
+    // Utils for cost calculation //
+    ////////////////////////////////
+    AK_FORCE_INLINE bool isSameNodeCodePoint(const DicNode *const dicNode) const {
+        return mDicNodeProperties.getNodeCodePoint()
+                == dicNode->mDicNodeProperties.getNodeCodePoint();
+    }
+
+    // TODO: remove
+    // TODO: rename getNextInputIndex
+    int16_t getInputIndex(int pointerId) const {
+        return mDicNodeState.mDicNodeStateInput.getInputIndex(pointerId);
+    }
+
+    ////////////////////////////////////
+    // Getter of features for scoring //
+    ////////////////////////////////////
+    float getSpatialDistanceForScoring() const {
+        return mDicNodeState.mDicNodeStateScoring.getSpatialDistance();
+    }
+
+    float getLanguageDistanceForScoring() const {
+        return mDicNodeState.mDicNodeStateScoring.getLanguageDistance();
+    }
+
+    float getLanguageDistanceRatePerWordForScoring() const {
+        const float langDist = getLanguageDistanceForScoring();
+        const float totalWordCount =
+                static_cast<float>(mDicNodeState.mDicNodeStatePrevWord.getPrevWordCount() + 1);
+        return langDist / totalWordCount;
+    }
+
+    float getRawLength() const {
+        return mDicNodeState.mDicNodeStateScoring.getRawLength();
+    }
+
+    bool isLessThanOneErrorForScoring() const {
+        return mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount()
+                + mDicNodeState.mDicNodeStateScoring.getProximityCorrectionCount() <= 1;
+    }
+
+    DoubleLetterLevel getDoubleLetterLevel() const {
+        return mDicNodeState.mDicNodeStateScoring.getDoubleLetterLevel();
+    }
+
+    void setDoubleLetterLevel(DoubleLetterLevel doubleLetterLevel) {
+        mDicNodeState.mDicNodeStateScoring.setDoubleLetterLevel(doubleLetterLevel);
+    }
+
+    uint8_t getFlags() const {
+        return mDicNodeProperties.getFlags();
+    }
+
+    int getAttributesPos() const {
+        return mDicNodeProperties.getAttributesPos();
+    }
+
+    inline uint16_t getDepth() const {
+        return mDicNodeProperties.getDepth();
+    }
+
+    AK_FORCE_INLINE void dump(const char *tag) const {
+#if DEBUG_DICT
+        DUMP_WORD_AND_SCORE(tag);
+#if DEBUG_DUMP_ERROR
+        mProfiler.dump();
+#endif
+#endif
+    }
+
+    void setReleaseListener(DicNodeReleaseListener *releaseListener) {
+        mReleaseListener = releaseListener;
+    }
+
+    AK_FORCE_INLINE bool compare(const DicNode *right) {
+        if (!isUsed() && !right->isUsed()) {
+            // Compare pointer values here for stable comparison
+            return this > right;
+        }
+        if (!isUsed()) {
+            return true;
+        }
+        if (!right->isUsed()) {
+            return false;
+        }
+        const float diff =
+                right->getNormalizedCompoundDistance() - getNormalizedCompoundDistance();
+        static const float MIN_DIFF = 0.000001f;
+        if (diff > MIN_DIFF) {
+            return true;
+        } else if (diff < -MIN_DIFF) {
+            return false;
+        }
+        const int depth = getDepth();
+        const int depthDiff = right->getDepth() - depth;
+        if (depthDiff != 0) {
+            return depthDiff > 0;
+        }
+        for (int i = 0; i < depth; ++i) {
+            const int codePoint = mDicNodeState.mDicNodeStateOutput.getCodePointAt(i);
+            const int rightCodePoint = right->mDicNodeState.mDicNodeStateOutput.getCodePointAt(i);
+            if (codePoint != rightCodePoint) {
+                return rightCodePoint > codePoint;
+            }
+        }
+        // Compare pointer values here for stable comparison
+        return this > right;
+    }
+
+ private:
+    DicNodeProperties mDicNodeProperties;
+    DicNodeState mDicNodeState;
+    // TODO: Remove
+    bool mIsCachedForNextSuggestion;
+    bool mIsUsed;
+    DicNodeReleaseListener *mReleaseListener;
+
+    AK_FORCE_INLINE int getTotalInputIndex() const {
+        int index = 0;
+        for (int i = 0; i < MAX_POINTER_COUNT_G; i++) {
+            index += mDicNodeState.mDicNodeStateInput.getInputIndex(i);
+        }
+        return index;
+    }
+
+    // Caveat: Must not be called outside Weighting
+    // This restriction is guaranteed by "friend"
+    AK_FORCE_INLINE void addCost(const float spatialCost, const float languageCost,
+            const bool doNormalization, const int inputSize, const bool isEditCorrection,
+            const bool isProximityCorrection) {
+        if (DEBUG_GEO_FULL) {
+            LOGI_SHOW_ADD_COST_PROP;
+        }
+        mDicNodeState.mDicNodeStateScoring.addCost(spatialCost, languageCost, doNormalization,
+                inputSize, getTotalInputIndex(), isEditCorrection, isProximityCorrection);
+    }
+
+    // Caveat: Must not be called outside Weighting
+    // This restriction is guaranteed by "friend"
+    AK_FORCE_INLINE void forwardInputIndex(const int pointerId, const int count,
+            const bool overwritesPrevCodePointByNodeCodePoint) {
+        if (count == 0) {
+            return;
+        }
+        mDicNodeState.mDicNodeStateInput.forwardInputIndex(pointerId, count);
+        if (overwritesPrevCodePointByNodeCodePoint) {
+            mDicNodeState.mDicNodeStateInput.setPrevCodePoint(0, getNodeCodePoint());
+        }
+    }
+
+    AK_FORCE_INLINE void updateInputIndexG(DicNode_InputStateG *inputStateG) {
+        mDicNodeState.mDicNodeStateInput.updateInputIndexG(inputStateG->mPointerId,
+                inputStateG->mInputIndex, inputStateG->mPrevCodePoint,
+                inputStateG->mTerminalDiffCost, inputStateG->mRawLength);
+        mDicNodeState.mDicNodeStateScoring.addRawLength(inputStateG->mRawLength);
+        mDicNodeState.mDicNodeStateScoring.setDoubleLetterLevel(inputStateG->mDoubleLetterLevel);
+    }
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
new file mode 100644
index 0000000..d3f28a8
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_PRIORITY_QUEUE_H
+#define LATINIME_DIC_NODE_PRIORITY_QUEUE_H
+
+#include <queue>
+#include <vector>
+
+#include "defines.h"
+#include "dic_node.h"
+#include "dic_node_release_listener.h"
+
+#define MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY 200
+
+namespace latinime {
+
+class DicNodePriorityQueue : public DicNodeReleaseListener {
+ public:
+    AK_FORCE_INLINE DicNodePriorityQueue()
+            : MAX_CAPACITY(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
+              mMaxSize(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY), mDicNodesBuf(), mUnusedNodeIndices(),
+              mNextUnusedNodeId(0), mDicNodesQueue() {
+        mDicNodesBuf.resize(MAX_CAPACITY + 1);
+        mUnusedNodeIndices.resize(MAX_CAPACITY + 1);
+        reset();
+    }
+
+    // Non virtual inline destructor -- never inherit this class
+    AK_FORCE_INLINE ~DicNodePriorityQueue() {}
+
+    int getSize() const {
+        return static_cast<int>(mDicNodesQueue.size());
+    }
+
+    int getMaxSize() const {
+        return mMaxSize;
+    }
+
+    AK_FORCE_INLINE void setMaxSize(const int maxSize) {
+        mMaxSize = min(maxSize, MAX_CAPACITY);
+    }
+
+    AK_FORCE_INLINE void reset() {
+        clearAndResize(MAX_CAPACITY);
+    }
+
+    AK_FORCE_INLINE void clear() {
+        clearAndResize(mMaxSize);
+    }
+
+    AK_FORCE_INLINE void clearAndResize(const int maxSize) {
+        while (!mDicNodesQueue.empty()) {
+            mDicNodesQueue.pop();
+        }
+        setMaxSize(maxSize);
+        for (int i = 0; i < MAX_CAPACITY + 1; ++i) {
+            mDicNodesBuf[i].remove();
+            mDicNodesBuf[i].setReleaseListener(this);
+            mUnusedNodeIndices[i] = i == MAX_CAPACITY ? NOT_A_NODE_ID : static_cast<int>(i) + 1;
+        }
+        mNextUnusedNodeId = 0;
+    }
+
+    AK_FORCE_INLINE DicNode *newDicNode(DicNode *dicNode) {
+        DicNode *newNode = searchEmptyDicNode();
+        if (newNode) {
+            DicNodeUtils::initByCopy(dicNode, newNode);
+            return newNode;
+        }
+        return 0;
+    }
+
+    // Copy
+    AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode) {
+        return copyPush(dicNode, mMaxSize);
+    }
+
+    AK_FORCE_INLINE void copyPop(DicNode *dest) {
+        if (mDicNodesQueue.empty()) {
+            ASSERT(false);
+            return;
+        }
+        DicNode *node = mDicNodesQueue.top();
+        if (dest) {
+            DicNodeUtils::initByCopy(node, dest);
+        }
+        node->remove();
+        mDicNodesQueue.pop();
+    }
+
+    void onReleased(DicNode *dicNode) {
+        const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
+        if (mUnusedNodeIndices[index] != NOT_A_NODE_ID) {
+            // it's already released
+            return;
+        }
+        mUnusedNodeIndices[index] = mNextUnusedNodeId;
+        mNextUnusedNodeId = index;
+        ASSERT(index >= 0 && index < (MAX_CAPACITY + 1));
+    }
+
+    AK_FORCE_INLINE void dump() const {
+        AKLOGI("\n\n\n\n\n===========================");
+        for (int i = 0; i < MAX_CAPACITY + 1; ++i) {
+            if (mDicNodesBuf[i].isUsed()) {
+                mDicNodesBuf[i].dump("QUEUE: ");
+            }
+        }
+        AKLOGI("===========================\n\n\n\n\n");
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DicNodePriorityQueue);
+    static const int NOT_A_NODE_ID = -1;
+
+    AK_FORCE_INLINE static bool compareDicNode(DicNode *left, DicNode *right) {
+        return left->compare(right);
+    }
+
+    struct DicNodeComparator {
+        bool operator ()(DicNode *left, DicNode *right) {
+            return compareDicNode(left, right);
+        }
+    };
+
+    typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
+    const int MAX_CAPACITY;
+    int mMaxSize;
+    std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively
+    std::vector<int> mUnusedNodeIndices;
+    int mNextUnusedNodeId;
+    DicNodesQueue mDicNodesQueue;
+
+    inline bool isFull(const int maxSize) const {
+        return getSize() >= maxSize;
+    }
+
+    AK_FORCE_INLINE void pop() {
+        copyPop(0);
+    }
+
+    AK_FORCE_INLINE bool betterThanWorstDicNode(DicNode *dicNode) const {
+        DicNode *worstNode = mDicNodesQueue.top();
+        if (!worstNode) {
+            return true;
+        }
+        return compareDicNode(dicNode, worstNode);
+    }
+
+    AK_FORCE_INLINE DicNode *searchEmptyDicNode() {
+        // TODO: Currently O(n) but should be improved to O(1)
+        if (MAX_CAPACITY == 0) {
+            return 0;
+        }
+        if (mNextUnusedNodeId == NOT_A_NODE_ID) {
+            AKLOGI("No unused node found.");
+            for (int i = 0; i < MAX_CAPACITY + 1; ++i) {
+                AKLOGI("Dump node availability, %d, %d, %d",
+                        i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]);
+            }
+            ASSERT(false);
+            return 0;
+        }
+        DicNode *dicNode = &mDicNodesBuf[mNextUnusedNodeId];
+        markNodeAsUsed(dicNode);
+        return dicNode;
+    }
+
+    AK_FORCE_INLINE void markNodeAsUsed(DicNode *dicNode) {
+        const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
+        mNextUnusedNodeId = mUnusedNodeIndices[index];
+        mUnusedNodeIndices[index] = NOT_A_NODE_ID;
+        ASSERT(index >= 0 && index < (MAX_CAPACITY + 1));
+    }
+
+    AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) {
+        if (!dicNode) {
+            return 0;
+        }
+        if (!isFull(maxSize)) {
+            mDicNodesQueue.push(dicNode);
+            return dicNode;
+        }
+        if (betterThanWorstDicNode(dicNode)) {
+            pop();
+            mDicNodesQueue.push(dicNode);
+            return dicNode;
+        }
+        dicNode->remove();
+        return 0;
+    }
+
+    // Copy
+    AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode, const int maxSize) {
+        return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize);
+    }
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_profiler.h b/native/jni/src/suggest/core/dicnode/dic_node_profiler.h
new file mode 100644
index 0000000..90f75d0
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_profiler.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_PROFILER_H
+#define LATINIME_DIC_NODE_PROFILER_H
+
+#include "defines.h"
+
+#if DEBUG_DICT
+#define PROF_SPACE_SUBSTITUTION(profiler) profiler.profSpaceSubstitution()
+#define PROF_SPACE_OMISSION(profiler) profiler.profSpaceOmission()
+#define PROF_ADDITIONAL_PROXIMITY(profiler) profiler.profAdditionalProximity()
+#define PROF_SUBSTITUTION(profiler) profiler.profSubstitution()
+#define PROF_OMISSION(profiler) profiler.profOmission()
+#define PROF_INSERTION(profiler) profiler.profInsertion()
+#define PROF_MATCH(profiler) profiler.profMatch()
+#define PROF_COMPLETION(profiler) profiler.profCompletion()
+#define PROF_TRANSPOSITION(profiler) profiler.profTransposition()
+#define PROF_NEARESTKEY(profiler) profiler.profNearestKey()
+#define PROF_TERMINAL(profiler) profiler.profTerminal()
+#define PROF_NEW_WORD(profiler) profiler.profNewWord()
+#define PROF_NEW_WORD_BIGRAM(profiler) profiler.profNewWordBigram()
+#define PROF_NODE_RESET(profiler) profiler.reset()
+#define PROF_NODE_COPY(src, dest) dest.copy(src)
+#else
+#define PROF_SPACE_SUBSTITUTION(profiler)
+#define PROF_SPACE_OMISSION(profiler)
+#define PROF_ADDITONAL_PROXIMITY(profiler)
+#define PROF_SUBSTITUTION(profiler)
+#define PROF_OMISSION(profiler)
+#define PROF_INSERTION(profiler)
+#define PROF_MATCH(profiler)
+#define PROF_COMPLETION(profiler)
+#define PROF_TRANSPOSITION(profiler)
+#define PROF_NEARESTKEY(profiler)
+#define PROF_TERMINAL(profiler)
+#define PROF_NEW_WORD(profiler)
+#define PROF_NEW_WORD_BIGRAM(profiler)
+#define PROF_NODE_RESET(profiler)
+#define PROF_NODE_COPY(src, dest)
+#endif
+
+namespace latinime {
+
+class DicNodeProfiler {
+ public:
+#if DEBUG_DICT
+    AK_FORCE_INLINE DicNodeProfiler()
+            : mProfOmission(0), mProfInsertion(0), mProfTransposition(0),
+              mProfAdditionalProximity(0), mProfSubstitution(0),
+              mProfSpaceSubstitution(0), mProfSpaceOmission(0),
+              mProfMatch(0), mProfCompletion(0), mProfTerminal(0),
+              mProfNearestKey(0), mProfNewWord(0), mProfNewWordBigram(0) {}
+
+    int mProfOmission;
+    int mProfInsertion;
+    int mProfTransposition;
+    int mProfAdditionalProximity;
+    int mProfSubstitution;
+    int mProfSpaceSubstitution;
+    int mProfSpaceOmission;
+    int mProfMatch;
+    int mProfCompletion;
+    int mProfTerminal;
+    int mProfNearestKey;
+    int mProfNewWord;
+    int mProfNewWordBigram;
+
+    void profSpaceSubstitution() {
+        ++mProfSpaceSubstitution;
+    }
+
+    void profSpaceOmission() {
+        ++mProfSpaceOmission;
+    }
+
+    void profAdditionalProximity() {
+        ++mProfAdditionalProximity;
+    }
+
+    void profSubstitution() {
+        ++mProfSubstitution;
+    }
+
+    void profOmission() {
+        ++mProfOmission;
+    }
+
+    void profInsertion() {
+        ++mProfInsertion;
+    }
+
+    void profMatch() {
+        ++mProfMatch;
+    }
+
+    void profCompletion() {
+        ++mProfCompletion;
+    }
+
+    void profTransposition() {
+        ++mProfTransposition;
+    }
+
+    void profNearestKey() {
+        ++mProfNearestKey;
+    }
+
+    void profTerminal() {
+        ++mProfTerminal;
+    }
+
+    void profNewWord() {
+        ++mProfNewWord;
+    }
+
+    void profNewWordBigram() {
+        ++mProfNewWordBigram;
+    }
+
+    void reset() {
+        mProfSpaceSubstitution = 0;
+        mProfSpaceOmission = 0;
+        mProfAdditionalProximity = 0;
+        mProfSubstitution = 0;
+        mProfOmission = 0;
+        mProfInsertion = 0;
+        mProfMatch = 0;
+        mProfCompletion = 0;
+        mProfTransposition = 0;
+        mProfNearestKey = 0;
+        mProfTerminal = 0;
+        mProfNewWord = 0;
+        mProfNewWordBigram = 0;
+    }
+
+    void copy(const DicNodeProfiler *const profiler) {
+        mProfSpaceSubstitution = profiler->mProfSpaceSubstitution;
+        mProfSpaceOmission = profiler->mProfSpaceOmission;
+        mProfAdditionalProximity = profiler->mProfAdditionalProximity;
+        mProfSubstitution = profiler->mProfSubstitution;
+        mProfOmission = profiler->mProfOmission;
+        mProfInsertion = profiler->mProfInsertion;
+        mProfMatch = profiler->mProfMatch;
+        mProfCompletion = profiler->mProfCompletion;
+        mProfTransposition = profiler->mProfTransposition;
+        mProfNearestKey = profiler->mProfNearestKey;
+        mProfTerminal = profiler->mProfTerminal;
+        mProfNewWord = profiler->mProfNewWord;
+        mProfNewWordBigram = profiler->mProfNewWordBigram;
+    }
+
+    void dump() const {
+        AKLOGI("O %d, I %d, T %d, AP %d, S %d, SS %d, SO %d, M %d, C %d, TE %d, NW = %d, NWB = %d",
+                mProfOmission, mProfInsertion, mProfTransposition, mProfAdditionalProximity,
+                mProfSubstitution, mProfSpaceSubstitution, mProfSpaceOmission, mProfMatch,
+                mProfCompletion, mProfTerminal, mProfNewWord, mProfNewWordBigram);
+    }
+#else
+    DicNodeProfiler() {}
+#endif
+ private:
+    // Caution!!!
+    // Use a default copy constructor and an assign operator because shallow copies are ok
+    // for this class
+};
+}
+#endif // LATINIME_DIC_NODE_PROFILER_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/dic_node_properties.h
new file mode 100644
index 0000000..173ef35
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_properties.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_PROPERTIES_H
+#define LATINIME_DIC_NODE_PROPERTIES_H
+
+#include <stdint.h>
+
+#include "defines.h"
+
+namespace latinime {
+
+/**
+ * Node for traversing the lexicon trie.
+ */
+class DicNodeProperties {
+ public:
+    AK_FORCE_INLINE DicNodeProperties()
+            : mPos(0), mFlags(0), mChildrenPos(0), mAttributesPos(0), mSiblingPos(0),
+              mChildrenCount(0), mProbability(0), mBigramProbability(0), mNodeCodePoint(0),
+              mDepth(0), mLeavingDepth(0), mIsTerminal(false), mHasMultipleChars(false),
+              mHasChildren(false) {
+    }
+
+    virtual ~DicNodeProperties() {}
+
+    // Should be called only once per DicNode is initialized.
+    void init(const int pos, const uint8_t flags, const int childrenPos, const int attributesPos,
+            const int siblingPos, const int nodeCodePoint, const int childrenCount,
+            const int probability, const int bigramProbability, const bool isTerminal,
+            const bool hasMultipleChars, const bool hasChildren, const uint16_t depth,
+            const uint16_t terminalDepth) {
+        mPos = pos;
+        mFlags = flags;
+        mChildrenPos = childrenPos;
+        mAttributesPos = attributesPos;
+        mSiblingPos = siblingPos;
+        mNodeCodePoint = nodeCodePoint;
+        mChildrenCount = childrenCount;
+        mProbability = probability;
+        mBigramProbability = bigramProbability;
+        mIsTerminal = isTerminal;
+        mHasMultipleChars = hasMultipleChars;
+        mHasChildren = hasChildren;
+        mDepth = depth;
+        mLeavingDepth = terminalDepth;
+    }
+
+    // Init for copy
+    void init(const DicNodeProperties *const nodeProp) {
+        mPos = nodeProp->mPos;
+        mFlags = nodeProp->mFlags;
+        mChildrenPos = nodeProp->mChildrenPos;
+        mAttributesPos = nodeProp->mAttributesPos;
+        mSiblingPos = nodeProp->mSiblingPos;
+        mNodeCodePoint = nodeProp->mNodeCodePoint;
+        mChildrenCount = nodeProp->mChildrenCount;
+        mProbability = nodeProp->mProbability;
+        mBigramProbability = nodeProp->mBigramProbability;
+        mIsTerminal = nodeProp->mIsTerminal;
+        mHasMultipleChars = nodeProp->mHasMultipleChars;
+        mHasChildren = nodeProp->mHasChildren;
+        mDepth = nodeProp->mDepth;
+        mLeavingDepth = nodeProp->mLeavingDepth;
+    }
+
+    // Init as passing child
+    void init(const DicNodeProperties *const nodeProp, const int codePoint) {
+        mPos = nodeProp->mPos;
+        mFlags = nodeProp->mFlags;
+        mChildrenPos = nodeProp->mChildrenPos;
+        mAttributesPos = nodeProp->mAttributesPos;
+        mSiblingPos = nodeProp->mSiblingPos;
+        mNodeCodePoint = codePoint; // Overwrite the node char of a passing child
+        mChildrenCount = nodeProp->mChildrenCount;
+        mProbability = nodeProp->mProbability;
+        mBigramProbability = nodeProp->mBigramProbability;
+        mIsTerminal = nodeProp->mIsTerminal;
+        mHasMultipleChars = nodeProp->mHasMultipleChars;
+        mHasChildren = nodeProp->mHasChildren;
+        mDepth = nodeProp->mDepth + 1; // Increment the depth of a passing child
+        mLeavingDepth = nodeProp->mLeavingDepth;
+    }
+
+    int getPos() const {
+        return mPos;
+    }
+
+    uint8_t getFlags() const {
+        return mFlags;
+    }
+
+    int getChildrenPos() const {
+        return mChildrenPos;
+    }
+
+    int getAttributesPos() const {
+        return mAttributesPos;
+    }
+
+    int getChildrenCount() const {
+        return mChildrenCount;
+    }
+
+    int getProbability() const {
+        return mProbability;
+    }
+
+    int getNodeCodePoint() const {
+        return mNodeCodePoint;
+    }
+
+    uint16_t getDepth() const {
+        return mDepth;
+    }
+
+    // TODO: Move to output?
+    uint16_t getLeavingDepth() const {
+        return mLeavingDepth;
+    }
+
+    bool isTerminal() const {
+        return mIsTerminal;
+    }
+
+    bool hasMultipleChars() const {
+        return mHasMultipleChars;
+    }
+
+    bool hasChildren() const {
+        return mChildrenCount > 0 || mDepth != mLeavingDepth;
+    }
+
+ private:
+    // Caution!!!
+    // Use a default copy constructor and an assign operator because shallow copies are ok
+    // for this class
+
+    // Not used
+    int getSiblingPos() const {
+        return mSiblingPos;
+    }
+
+    int mPos;
+    uint8_t mFlags;
+    int mChildrenPos;
+    int mAttributesPos;
+    int mSiblingPos;
+    int mChildrenCount;
+    int mProbability;
+    int mBigramProbability; // not used for now
+    int mNodeCodePoint;
+    uint16_t mDepth;
+    uint16_t mLeavingDepth;
+    bool mIsTerminal;
+    bool mHasMultipleChars;
+    bool mHasChildren;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_PROPERTIES_H
diff --git a/native/jni/src/suggest/typing_suggest.cpp b/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
similarity index 62%
copy from native/jni/src/suggest/typing_suggest.cpp
copy to native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
index 56bd5b6..2a81c3c 100644
--- a/native/jni/src/suggest/typing_suggest.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
@@ -14,12 +14,20 @@
  * limitations under the License.
  */
 
-#include "typing_suggest.h"
+#ifndef LATINIME_DIC_NODE_RELEASE_LISTENER_H
+#define LATINIME_DIC_NODE_RELEASE_LISTENER_H
+
+#include "defines.h"
 
 namespace latinime {
-    SuggestInterface *(*TypingSuggest::sTypingSuggestFactoryMethod)() = 0;
 
-    TypingSuggest::~TypingSuggest() {
-        delete mSuggestInterface;
-    }
+class DicNodeReleaseListener {
+ public:
+    DicNodeReleaseListener() {}
+    virtual ~DicNodeReleaseListener() {}
+    virtual void onReleased(DicNode *dicNode) = 0;
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DicNodeReleaseListener);
+};
 } // namespace latinime
+#endif // LATINIME_DIC_NODE_RELEASE_LISTENER_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state.h b/native/jni/src/suggest/core/dicnode/dic_node_state.h
new file mode 100644
index 0000000..239b63c
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_STATE_H
+#define LATINIME_DIC_NODE_STATE_H
+
+#include "defines.h"
+#include "dic_node_state_input.h"
+#include "dic_node_state_output.h"
+#include "dic_node_state_prevword.h"
+#include "dic_node_state_scoring.h"
+
+namespace latinime {
+
+class DicNodeState {
+ public:
+    DicNodeStateInput mDicNodeStateInput;
+    DicNodeStateOutput mDicNodeStateOutput;
+    DicNodeStatePrevWord mDicNodeStatePrevWord;
+    DicNodeStateScoring mDicNodeStateScoring;
+
+    AK_FORCE_INLINE DicNodeState()
+            : mDicNodeStateInput(), mDicNodeStateOutput(), mDicNodeStatePrevWord(),
+              mDicNodeStateScoring() {
+    }
+
+    virtual ~DicNodeState() {}
+
+    // Init with prevWordPos
+    void init(const int prevWordPos) {
+        mDicNodeStateInput.init();
+        mDicNodeStateOutput.init();
+        mDicNodeStatePrevWord.init(prevWordPos);
+        mDicNodeStateScoring.init();
+    }
+
+    // Init by copy
+    AK_FORCE_INLINE void init(const DicNodeState *const src) {
+        mDicNodeStateInput.init(&src->mDicNodeStateInput);
+        mDicNodeStateOutput.init(&src->mDicNodeStateOutput);
+        mDicNodeStatePrevWord.init(&src->mDicNodeStatePrevWord);
+        mDicNodeStateScoring.init(&src->mDicNodeStateScoring);
+    }
+
+    // Init by copy and adding subword
+    void init(const DicNodeState *const src, const uint16_t additionalSubwordLength,
+            const int *const additionalSubword) {
+        init(src);
+        mDicNodeStateOutput.addSubword(additionalSubwordLength, additionalSubword);
+    }
+
+ private:
+    // Caution!!!
+    // Use a default copy constructor and an assign operator because shallow copies are ok
+    // for this class
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_STATE_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state_input.h b/native/jni/src/suggest/core/dicnode/dic_node_state_input.h
new file mode 100644
index 0000000..7ad3e3e
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state_input.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_STATE_INPUT_H
+#define LATINIME_DIC_NODE_STATE_INPUT_H
+
+#include "defines.h"
+
+namespace latinime {
+
+// TODO: Have a .cpp for this class
+class DicNodeStateInput {
+ public:
+    DicNodeStateInput() {}
+    virtual ~DicNodeStateInput() {}
+
+    // TODO: Merge into DicNodeStatePrevWord::truncate
+    void truncate(const int commitPoint) {
+        mInputIndex[0] -= commitPoint;
+    }
+
+    void init() {
+        for (int i = 0; i < MAX_POINTER_COUNT_G; i++) {
+            // TODO: The initial value for mInputIndex should be -1?
+            //mInputIndex[i] = i == 0 ? 0 : -1;
+            mInputIndex[i] = 0;
+            mPrevCodePoint[i] = NOT_A_CODE_POINT;
+            mTerminalDiffCost[i] = static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
+        }
+    }
+
+    void init(const DicNodeStateInput *const src, const bool resetTerminalDiffCost) {
+        for (int i = 0; i < MAX_POINTER_COUNT_G; i++) {
+             mInputIndex[i] = src->mInputIndex[i];
+             mPrevCodePoint[i] = src->mPrevCodePoint[i];
+        mTerminalDiffCost[i] = resetTerminalDiffCost ?
+                static_cast<float>(MAX_VALUE_FOR_WEIGHTING) : src->mTerminalDiffCost[i];
+         }
+    }
+
+    void updateInputIndexG(const int pointerId, const int inputIndex,
+            const int prevCodePoint, const float terminalDiffCost, const float rawLength) {
+        mInputIndex[pointerId] = inputIndex;
+        mPrevCodePoint[pointerId] = prevCodePoint;
+        mTerminalDiffCost[pointerId] = terminalDiffCost;
+    }
+
+    void init(const DicNodeStateInput *const src) {
+        init(src, false);
+    }
+
+    // For transposition
+    void setPrevCodePoint(const int pointerId, const int c) {
+        mPrevCodePoint[pointerId] = c;
+    }
+
+    void forwardInputIndex(const int pointerId, const int val) {
+        if (mInputIndex[pointerId] < 0) {
+            mInputIndex[pointerId] = val;
+        } else {
+            mInputIndex[pointerId] = mInputIndex[pointerId] + val;
+        }
+    }
+
+    int getInputIndex(const int pointerId) const {
+        // when "inputIndex" exceeds "inputSize", auto-completion needs to be done
+        return mInputIndex[pointerId];
+    }
+
+    int getPrevCodePoint(const int pointerId) const {
+        return mPrevCodePoint[pointerId];
+    }
+
+    float getTerminalDiffCost(const int pointerId) const {
+        return mTerminalDiffCost[pointerId];
+    }
+
+ private:
+    // Caution!!!
+    // Use a default copy constructor and an assign operator because shallow copies are ok
+    // for this class
+    int mInputIndex[MAX_POINTER_COUNT_G];
+    int mPrevCodePoint[MAX_POINTER_COUNT_G];
+    float mTerminalDiffCost[MAX_POINTER_COUNT_G];
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_STATE_INPUT_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state_output.h b/native/jni/src/suggest/core/dicnode/dic_node_state_output.h
new file mode 100644
index 0000000..1d4f50a
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state_output.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_STATE_OUTPUT_H
+#define LATINIME_DIC_NODE_STATE_OUTPUT_H
+
+#include <cstring> // for memcpy()
+#include <stdint.h>
+
+#include "defines.h"
+
+namespace latinime {
+
+class DicNodeStateOutput {
+ public:
+    DicNodeStateOutput() : mOutputtedLength(0) {
+        init();
+    }
+
+    virtual ~DicNodeStateOutput() {}
+
+    void init() {
+        mOutputtedLength = 0;
+        mWordBuf[0] = 0;
+    }
+
+    void init(const DicNodeStateOutput *const stateOutput) {
+        memcpy(mWordBuf, stateOutput->mWordBuf,
+                stateOutput->mOutputtedLength * sizeof(mWordBuf[0]));
+        mOutputtedLength = stateOutput->mOutputtedLength;
+        if (mOutputtedLength < MAX_WORD_LENGTH) {
+            mWordBuf[mOutputtedLength] = 0;
+        }
+    }
+
+    void addSubword(const uint16_t additionalSubwordLength, const int *const additionalSubword) {
+        if (additionalSubword) {
+            memcpy(&mWordBuf[mOutputtedLength], additionalSubword,
+                    additionalSubwordLength * sizeof(mWordBuf[0]));
+            mOutputtedLength = static_cast<uint16_t>(mOutputtedLength + additionalSubwordLength);
+            if (mOutputtedLength < MAX_WORD_LENGTH) {
+                mWordBuf[mOutputtedLength] = 0;
+            }
+        }
+    }
+
+    // TODO: Remove
+    int getCodePointAt(const int id) const {
+        return mWordBuf[id];
+    }
+
+    // TODO: Move to private
+    int mWordBuf[MAX_WORD_LENGTH];
+
+ private:
+    // Caution!!!
+    // Use a default copy constructor and an assign operator because shallow copies are ok
+    // for this class
+    uint16_t mOutputtedLength;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_STATE_OUTPUT_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h b/native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h
new file mode 100644
index 0000000..e3b892b
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_STATE_PREVWORD_H
+#define LATINIME_DIC_NODE_STATE_PREVWORD_H
+
+#include <cstring> // for memset()
+#include <stdint.h>
+
+#include "defines.h"
+#include "dic_node_utils.h"
+
+namespace latinime {
+
+class DicNodeStatePrevWord {
+ public:
+    AK_FORCE_INLINE DicNodeStatePrevWord()
+            : mPrevWordCount(0), mPrevWordLength(0), mPrevWordStart(0), mPrevWordProbability(0),
+              mPrevWordNodePos(0) {
+        memset(mPrevWord, 0, sizeof(mPrevWord));
+        memset(mPrevSpacePositions, 0, sizeof(mPrevSpacePositions));
+    }
+
+    virtual ~DicNodeStatePrevWord() {}
+
+    void init() {
+        mPrevWordLength = 0;
+        mPrevWordCount = 0;
+        mPrevWordStart = 0;
+        mPrevWordProbability = -1;
+        mPrevWordNodePos = NOT_VALID_WORD;
+        memset(mPrevSpacePositions, 0, sizeof(mPrevSpacePositions));
+    }
+
+    void init(const int prevWordNodePos) {
+        mPrevWordLength = 0;
+        mPrevWordCount = 0;
+        mPrevWordStart = 0;
+        mPrevWordProbability = -1;
+        mPrevWordNodePos = prevWordNodePos;
+        memset(mPrevSpacePositions, 0, sizeof(mPrevSpacePositions));
+    }
+
+    // Init by copy
+    AK_FORCE_INLINE void init(const DicNodeStatePrevWord *const prevWord) {
+        mPrevWordLength = prevWord->mPrevWordLength;
+        mPrevWordCount = prevWord->mPrevWordCount;
+        mPrevWordStart = prevWord->mPrevWordStart;
+        mPrevWordProbability = prevWord->mPrevWordProbability;
+        mPrevWordNodePos = prevWord->mPrevWordNodePos;
+        memcpy(mPrevWord, prevWord->mPrevWord, prevWord->mPrevWordLength * sizeof(mPrevWord[0]));
+        memcpy(mPrevSpacePositions, prevWord->mPrevSpacePositions, sizeof(mPrevSpacePositions));
+    }
+
+    void init(const int16_t prevWordCount, const int16_t prevWordProbability,
+            const int prevWordNodePos, const int *const src0, const int16_t length0,
+            const int *const src1, const int16_t length1, const int *const prevSpacePositions,
+            const int lastInputIndex) {
+        mPrevWordCount = prevWordCount;
+        mPrevWordProbability = prevWordProbability;
+        mPrevWordNodePos = prevWordNodePos;
+        const int twoWordsLen =
+                DicNodeUtils::appendTwoWords(src0, length0, src1, length1, mPrevWord);
+        mPrevWord[twoWordsLen] = KEYCODE_SPACE;
+        mPrevWordStart = length0;
+        mPrevWordLength = static_cast<int16_t>(twoWordsLen + 1);
+        memcpy(mPrevSpacePositions, prevSpacePositions, sizeof(mPrevSpacePositions));
+        mPrevSpacePositions[mPrevWordCount - 1] = lastInputIndex;
+    }
+
+    void truncate(const int offset) {
+        // TODO: memmove
+        if (mPrevWordLength < offset) {
+            memset(mPrevWord, 0, sizeof(mPrevWord));
+            mPrevWordLength = 0;
+            return;
+        }
+        const int newPrevWordLength = mPrevWordLength - offset;
+        memmove(mPrevWord, &mPrevWord[offset], newPrevWordLength * sizeof(mPrevWord[0]));
+        mPrevWordLength = newPrevWordLength;
+    }
+
+    void outputSpacePositions(int *spaceIndices) const {
+        // Convert uint16_t to int
+        for (int i = 0; i < MAX_RESULTS; i++) {
+            spaceIndices[i] = mPrevSpacePositions[i];
+        }
+    }
+
+    // TODO: remove
+    int16_t getPrevWordLength() const {
+        return mPrevWordLength;
+    }
+
+    int16_t getPrevWordCount() const {
+        return mPrevWordCount;
+    }
+
+    int16_t getPrevWordStart() const {
+        return mPrevWordStart;
+    }
+
+    int16_t getPrevWordProbability() const {
+        return mPrevWordProbability;
+    }
+
+    int getPrevWordNodePos() const {
+        return mPrevWordNodePos;
+    }
+
+    int getPrevWordCodePointAt(const int id) const {
+        return mPrevWord[id];
+    }
+
+    bool startsWith(const DicNodeStatePrevWord *const prefix, const int prefixLen) const {
+        if (prefixLen > mPrevWordLength) {
+            return false;
+        }
+        for (int i = 0; i < prefixLen; ++i) {
+            if (mPrevWord[i] != prefix->mPrevWord[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // TODO: Move to private
+    int mPrevWord[MAX_WORD_LENGTH];
+    // TODO: Move to private
+    int mPrevSpacePositions[MAX_RESULTS];
+
+ private:
+    // Caution!!!
+    // Use a default copy constructor and an assign operator because shallow copies are ok
+    // for this class
+    int16_t mPrevWordCount;
+    int16_t mPrevWordLength;
+    int16_t mPrevWordStart;
+    int16_t mPrevWordProbability;
+    int mPrevWordNodePos;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_STATE_PREVWORD_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
new file mode 100644
index 0000000..8e81632
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_STATE_SCORING_H
+#define LATINIME_DIC_NODE_STATE_SCORING_H
+
+#include <stdint.h>
+
+#include "defines.h"
+
+namespace latinime {
+
+class DicNodeStateScoring {
+ public:
+    AK_FORCE_INLINE DicNodeStateScoring()
+            : mDoubleLetterLevel(NOT_A_DOUBLE_LETTER),
+              mEditCorrectionCount(0), mProximityCorrectionCount(0),
+              mNormalizedCompoundDistance(0.0f), mSpatialDistance(0.0f), mLanguageDistance(0.0f),
+              mTotalPrevWordsLanguageCost(0.0f), mRawLength(0.0f) {
+    }
+
+    virtual ~DicNodeStateScoring() {}
+
+    void init() {
+        mEditCorrectionCount = 0;
+        mProximityCorrectionCount = 0;
+        mNormalizedCompoundDistance = 0.0f;
+        mSpatialDistance = 0.0f;
+        mLanguageDistance = 0.0f;
+        mTotalPrevWordsLanguageCost = 0.0f;
+        mRawLength = 0.0f;
+        mDoubleLetterLevel = NOT_A_DOUBLE_LETTER;
+    }
+
+    AK_FORCE_INLINE void init(const DicNodeStateScoring *const scoring) {
+        mEditCorrectionCount = scoring->mEditCorrectionCount;
+        mProximityCorrectionCount = scoring->mProximityCorrectionCount;
+        mNormalizedCompoundDistance = scoring->mNormalizedCompoundDistance;
+        mSpatialDistance = scoring->mSpatialDistance;
+        mLanguageDistance = scoring->mLanguageDistance;
+        mTotalPrevWordsLanguageCost = scoring->mTotalPrevWordsLanguageCost;
+        mRawLength = scoring->mRawLength;
+        mDoubleLetterLevel = scoring->mDoubleLetterLevel;
+    }
+
+    void addCost(const float spatialCost, const float languageCost, const bool doNormalization,
+            const int inputSize, const int totalInputIndex, const bool isEditCorrection,
+            const bool isProximityCorrection) {
+        addDistance(spatialCost, languageCost, doNormalization, inputSize, totalInputIndex);
+        if (isEditCorrection) {
+            ++mEditCorrectionCount;
+        }
+        if (isProximityCorrection) {
+            ++mProximityCorrectionCount;
+        }
+        if (languageCost > 0.0f) {
+            setTotalPrevWordsLanguageCost(mTotalPrevWordsLanguageCost + languageCost);
+        }
+    }
+
+    void addRawLength(const float rawLength) {
+        mRawLength += rawLength;
+    }
+
+    float getCompoundDistance() const {
+        return getCompoundDistance(1.0f);
+    }
+
+    float getCompoundDistance(const float languageWeight) const {
+        return mSpatialDistance + mLanguageDistance * languageWeight;
+    }
+
+    float getNormalizedCompoundDistance() const {
+        return mNormalizedCompoundDistance;
+    }
+
+    float getSpatialDistance() const {
+        return mSpatialDistance;
+    }
+
+    float getLanguageDistance() const {
+        return mLanguageDistance;
+    }
+
+    int16_t getEditCorrectionCount() const {
+        return mEditCorrectionCount;
+    }
+
+    int16_t getProximityCorrectionCount() const {
+        return mProximityCorrectionCount;
+    }
+
+    float getRawLength() const {
+        return mRawLength;
+    }
+
+    DoubleLetterLevel getDoubleLetterLevel() const {
+        return mDoubleLetterLevel;
+    }
+
+    void setDoubleLetterLevel(DoubleLetterLevel doubleLetterLevel) {
+        switch(doubleLetterLevel) {
+            case NOT_A_DOUBLE_LETTER:
+                break;
+            case A_DOUBLE_LETTER:
+                if (mDoubleLetterLevel != A_STRONG_DOUBLE_LETTER) {
+                    mDoubleLetterLevel = doubleLetterLevel;
+                }
+                break;
+            case A_STRONG_DOUBLE_LETTER:
+                mDoubleLetterLevel = doubleLetterLevel;
+                break;
+        }
+    }
+
+    float getTotalPrevWordsLanguageCost() const {
+        return mTotalPrevWordsLanguageCost;
+    }
+
+ private:
+    // Caution!!!
+    // Use a default copy constructor and an assign operator because shallow copies are ok
+    // for this class
+    DoubleLetterLevel mDoubleLetterLevel;
+
+    int16_t mEditCorrectionCount;
+    int16_t mProximityCorrectionCount;
+
+    float mNormalizedCompoundDistance;
+    float mSpatialDistance;
+    float mLanguageDistance;
+    float mTotalPrevWordsLanguageCost;
+    float mRawLength;
+
+    AK_FORCE_INLINE void addDistance(float spatialDistance, float languageDistance,
+            bool doNormalization, int inputSize, int totalInputIndex) {
+        mSpatialDistance += spatialDistance;
+        mLanguageDistance += languageDistance;
+        if (!doNormalization) {
+            mNormalizedCompoundDistance = mSpatialDistance + mLanguageDistance;
+        } else {
+            mNormalizedCompoundDistance = (mSpatialDistance + mLanguageDistance)
+                    / static_cast<float>(max(1, totalInputIndex));
+        }
+    }
+
+    //TODO: remove
+    AK_FORCE_INLINE void setTotalPrevWordsLanguageCost(float totalPrevWordsLanguageCost) {
+        mTotalPrevWordsLanguageCost = totalPrevWordsLanguageCost;
+    }
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_STATE_SCORING_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
new file mode 100644
index 0000000..031e706
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstring>
+#include <vector>
+
+#include "binary_format.h"
+#include "dic_node.h"
+#include "dic_node_utils.h"
+#include "dic_node_vector.h"
+#include "proximity_info.h"
+#include "proximity_info_state.h"
+
+namespace latinime {
+
+///////////////////////////////
+// Node initialization utils //
+///////////////////////////////
+
+/* static */ void DicNodeUtils::initAsRoot(const int rootPos, const uint8_t *const dicRoot,
+        const int prevWordNodePos, DicNode *newRootNode) {
+    int curPos = rootPos;
+    const int pos = curPos;
+    const int childrenCount = BinaryFormat::getGroupCountAndForwardPointer(dicRoot, &curPos);
+    const int childrenPos = curPos;
+    newRootNode->initAsRoot(pos, childrenPos, childrenCount, prevWordNodePos);
+}
+
+/*static */ void DicNodeUtils::initAsRootWithPreviousWord(const int rootPos,
+        const uint8_t *const dicRoot, DicNode *prevWordLastNode, DicNode *newRootNode) {
+    int curPos = rootPos;
+    const int pos = curPos;
+    const int childrenCount = BinaryFormat::getGroupCountAndForwardPointer(dicRoot, &curPos);
+    const int childrenPos = curPos;
+    newRootNode->initAsRootWithPreviousWord(prevWordLastNode, pos, childrenPos, childrenCount);
+}
+
+/* static */ void DicNodeUtils::initByCopy(DicNode *srcNode, DicNode *destNode) {
+    destNode->initByCopy(srcNode);
+}
+
+///////////////////////////////////
+// Traverse node expansion utils //
+///////////////////////////////////
+
+/* static */ void DicNodeUtils::createAndGetPassingChildNode(DicNode *dicNode,
+        const ProximityInfoState *pInfoState, const int pointIndex, const bool exactOnly,
+        DicNodeVector *childDicNodes) {
+    // Passing multiple chars node. No need to traverse child
+    const int codePoint = dicNode->getNodeTypedCodePoint();
+    const int baseLowerCaseCodePoint = toBaseLowerCase(codePoint);
+    const bool isMatch = isMatchedNodeCodePoint(pInfoState, pointIndex, exactOnly, codePoint);
+    if (isMatch || isIntentionalOmissionCodePoint(baseLowerCaseCodePoint)) {
+        childDicNodes->pushPassingChild(dicNode);
+    }
+}
+
+/* static */ int DicNodeUtils::createAndGetLeavingChildNode(DicNode *dicNode, int pos,
+        const uint8_t *const dicRoot, const int terminalDepth, const ProximityInfoState *pInfoState,
+        const int pointIndex, const bool exactOnly, const std::vector<int> *const codePointsFilter,
+        const ProximityInfo *const pInfo, DicNodeVector *childDicNodes) {
+    int nextPos = pos;
+    const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(dicRoot, &pos);
+    const bool hasMultipleChars = (0 != (BinaryFormat::FLAG_HAS_MULTIPLE_CHARS & flags));
+    const bool isTerminal = (0 != (BinaryFormat::FLAG_IS_TERMINAL & flags));
+    const bool hasChildren = BinaryFormat::hasChildrenInFlags(flags);
+
+    int codePoint = BinaryFormat::getCodePointAndForwardPointer(dicRoot, &pos);
+    ASSERT(NOT_A_CODE_POINT != codePoint);
+    const int nodeCodePoint = codePoint;
+    // TODO: optimize this
+    int additionalWordBuf[MAX_WORD_LENGTH];
+    uint16_t additionalSubwordLength = 0;
+    additionalWordBuf[additionalSubwordLength++] = codePoint;
+
+    do {
+        const int nextCodePoint = hasMultipleChars
+                ? BinaryFormat::getCodePointAndForwardPointer(dicRoot, &pos) : NOT_A_CODE_POINT;
+        const bool isLastChar = (NOT_A_CODE_POINT == nextCodePoint);
+        if (!isLastChar) {
+            additionalWordBuf[additionalSubwordLength++] = nextCodePoint;
+        }
+        codePoint = nextCodePoint;
+    } while (NOT_A_CODE_POINT != codePoint);
+
+    const int probability =
+            isTerminal ? BinaryFormat::readProbabilityWithoutMovingPointer(dicRoot, pos) : -1;
+    pos = BinaryFormat::skipProbability(flags, pos);
+    int childrenPos = hasChildren ? BinaryFormat::readChildrenPosition(dicRoot, flags, pos) : 0;
+    const int attributesPos = BinaryFormat::skipChildrenPosition(flags, pos);
+    const int siblingPos = BinaryFormat::skipChildrenPosAndAttributes(dicRoot, flags, pos);
+
+    if (isDicNodeFilteredOut(nodeCodePoint, pInfo, codePointsFilter)) {
+        return siblingPos;
+    }
+    if (!isMatchedNodeCodePoint(pInfoState, pointIndex, exactOnly, nodeCodePoint)) {
+        return siblingPos;
+    }
+    const int childrenCount = hasChildren
+            ? BinaryFormat::getGroupCountAndForwardPointer(dicRoot, &childrenPos) : 0;
+    childDicNodes->pushLeavingChild(dicNode, nextPos, flags, childrenPos, attributesPos, siblingPos,
+            nodeCodePoint, childrenCount, probability, -1 /* bigramProbability */, isTerminal,
+            hasMultipleChars, hasChildren, additionalSubwordLength, additionalWordBuf);
+    return siblingPos;
+}
+
+/* static */ bool DicNodeUtils::isDicNodeFilteredOut(const int nodeCodePoint,
+        const ProximityInfo *const pInfo, const std::vector<int> *const codePointsFilter) {
+    const int filterSize = codePointsFilter ? codePointsFilter->size() : 0;
+    if (filterSize <= 0) {
+        return false;
+    }
+    if (pInfo && (pInfo->getKeyIndexOf(nodeCodePoint) == NOT_AN_INDEX
+            || isIntentionalOmissionCodePoint(nodeCodePoint))) {
+        // If normalized nodeCodePoint is not on the keyboard or skippable, this child is never
+        // filtered.
+        return false;
+    }
+    const int lowerCodePoint = toLowerCase(nodeCodePoint);
+    const int baseLowerCodePoint = toBaseCodePoint(lowerCodePoint);
+    // TODO: Avoid linear search
+    for (int i = 0; i < filterSize; ++i) {
+        // Checking if a normalized code point is in filter characters when pInfo is not
+        // null. When pInfo is null, nodeCodePoint is used to check filtering without
+        // normalizing.
+        if ((pInfo && ((*codePointsFilter)[i] == lowerCodePoint
+                || (*codePointsFilter)[i] == baseLowerCodePoint))
+                        || (!pInfo && (*codePointsFilter)[i] == nodeCodePoint)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+/* static */ void DicNodeUtils::createAndGetAllLeavingChildNodes(DicNode *dicNode,
+        const uint8_t *const dicRoot, const ProximityInfoState *pInfoState, const int pointIndex,
+        const bool exactOnly, const std::vector<int> *const codePointsFilter,
+        const ProximityInfo *const pInfo, DicNodeVector *childDicNodes) {
+    const int terminalDepth = dicNode->getLeavingDepth();
+    const int childCount = dicNode->getChildrenCount();
+    int nextPos = dicNode->getChildrenPos();
+    for (int i = 0; i < childCount; i++) {
+        const int filterSize = codePointsFilter ? codePointsFilter->size() : 0;
+        nextPos = createAndGetLeavingChildNode(dicNode, nextPos, dicRoot, terminalDepth, pInfoState,
+                pointIndex, exactOnly, codePointsFilter, pInfo, childDicNodes);
+        if (!pInfo && filterSize > 0 && childDicNodes->exceeds(filterSize)) {
+            // All code points have been found.
+            break;
+        }
+    }
+}
+
+/* static */ void DicNodeUtils::getAllChildDicNodes(DicNode *dicNode, const uint8_t *const dicRoot,
+        DicNodeVector *childDicNodes) {
+    getProximityChildDicNodes(dicNode, dicRoot, 0, 0, false, childDicNodes);
+}
+
+/* static */ void DicNodeUtils::getProximityChildDicNodes(DicNode *dicNode,
+        const uint8_t *const dicRoot, const ProximityInfoState *pInfoState, const int pointIndex,
+        bool exactOnly, DicNodeVector *childDicNodes) {
+    if (dicNode->isTotalInputSizeExceedingLimit()) {
+        return;
+    }
+    if (!dicNode->isLeavingNode()) {
+        DicNodeUtils::createAndGetPassingChildNode(dicNode, pInfoState, pointIndex, exactOnly,
+                childDicNodes);
+    } else {
+        DicNodeUtils::createAndGetAllLeavingChildNodes(dicNode, dicRoot, pInfoState, pointIndex,
+                exactOnly, 0 /* codePointsFilter */, 0 /* pInfo */,
+                childDicNodes);
+    }
+}
+
+///////////////////
+// Scoring utils //
+///////////////////
+/**
+ * Computes the combined bigram / unigram cost for the given dicNode.
+ */
+/* static */ float DicNodeUtils::getBigramNodeImprobability(const uint8_t *const dicRoot,
+        const DicNode *const node, hash_map_compat<int, int16_t> *bigramCacheMap) {
+    if (node->isImpossibleBigramWord()) {
+        return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
+    }
+    const int probability = getBigramNodeProbability(dicRoot, node, bigramCacheMap);
+    // TODO: This equation to calculate the improbability looks unreasonable.  Investigate this.
+    const float cost = static_cast<float>(MAX_PROBABILITY - probability)
+            / static_cast<float>(MAX_PROBABILITY);
+    return cost;
+}
+
+/* static */ int DicNodeUtils::getBigramNodeProbability(const uint8_t *const dicRoot,
+        const DicNode *const node, hash_map_compat<int, int16_t> *bigramCacheMap) {
+    const int unigramProbability = node->getProbability();
+    const int encodedDiffOfBigramProbability =
+            getBigramNodeEncodedDiffProbability(dicRoot, node, bigramCacheMap);
+    if (NOT_A_PROBABILITY == encodedDiffOfBigramProbability) {
+        return backoff(unigramProbability);
+    }
+    return BinaryFormat::computeProbabilityForBigram(
+            unigramProbability, encodedDiffOfBigramProbability);
+}
+
+///////////////////////////////////////
+// Bigram / Unigram dictionary utils //
+///////////////////////////////////////
+
+/* static */ int16_t DicNodeUtils::getBigramNodeEncodedDiffProbability(const uint8_t *const dicRoot,
+        const DicNode *const node, hash_map_compat<int, int16_t> *bigramCacheMap) {
+    const int wordPos = node->getPos();
+    const int prevWordPos = node->getPrevWordPos();
+    return getBigramProbability(dicRoot, prevWordPos, wordPos, bigramCacheMap);
+}
+
+// TODO: Move this to BigramDictionary
+/* static */ int16_t DicNodeUtils::getBigramProbability(const uint8_t *const dicRoot, int pos,
+        const int nextPos, hash_map_compat<int, int16_t> *bigramCacheMap) {
+    // TODO: this is painfully slow compared to the method used in the previous version of the
+    // algorithm. Switch to that method.
+    if (NOT_VALID_WORD == pos) return NOT_A_PROBABILITY;
+    if (NOT_VALID_WORD == nextPos) return NOT_A_PROBABILITY;
+
+    // Create a hash code for the given node pair (based on Josh Bloch's effective Java).
+    // TODO: Use a real hash map data structure that deals with collisions.
+    int hash = 17;
+    hash = hash * 31 + pos;
+    hash = hash * 31 + nextPos;
+
+    hash_map_compat<int, int16_t>::const_iterator mapPos = bigramCacheMap->find(hash);
+    if (mapPos != bigramCacheMap->end()) {
+        return mapPos->second;
+    }
+    if (NOT_VALID_WORD == pos) {
+        return NOT_A_PROBABILITY;
+    }
+    const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(dicRoot, &pos);
+    if (0 == (flags & BinaryFormat::FLAG_HAS_BIGRAMS)) {
+        return NOT_A_PROBABILITY;
+    }
+    if (0 == (flags & BinaryFormat::FLAG_HAS_MULTIPLE_CHARS)) {
+        BinaryFormat::getCodePointAndForwardPointer(dicRoot, &pos);
+    } else {
+        pos = BinaryFormat::skipOtherCharacters(dicRoot, pos);
+    }
+    pos = BinaryFormat::skipChildrenPosition(flags, pos);
+    pos = BinaryFormat::skipProbability(flags, pos);
+    uint8_t bigramFlags;
+    int count = 0;
+    do {
+        bigramFlags = BinaryFormat::getFlagsAndForwardPointer(dicRoot, &pos);
+        const int bigramPos = BinaryFormat::getAttributeAddressAndForwardPointer(dicRoot,
+                bigramFlags, &pos);
+        if (bigramPos == nextPos) {
+            const int16_t probability = BinaryFormat::MASK_ATTRIBUTE_PROBABILITY & bigramFlags;
+            if (static_cast<int>(bigramCacheMap->size()) < MAX_BIGRAM_MAP_SIZE) {
+                (*bigramCacheMap)[hash] = probability;
+            }
+            return probability;
+        }
+        count++;
+    } while ((0 != (BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT & bigramFlags))
+            && count < MAX_BIGRAMS_CONSIDERED_PER_CONTEXT);
+    if (static_cast<int>(bigramCacheMap->size()) < MAX_BIGRAM_MAP_SIZE) {
+        // TODO: does this -1 mean NOT_VALID_WORD?
+        (*bigramCacheMap)[hash] = -1;
+    }
+    return NOT_A_PROBABILITY;
+}
+
+/* static */ int DicNodeUtils::getWordPos(const uint8_t *const dicRoot, const int *word,
+        const int wordLength) {
+    if (!word) {
+        return NOT_VALID_WORD;
+    }
+    return BinaryFormat::getTerminalPosition(
+            dicRoot, word, wordLength, false /* forceLowerCaseSearch */);
+}
+
+/* static */ bool DicNodeUtils::isMatchedNodeCodePoint(const ProximityInfoState *pInfoState,
+        const int pointIndex, const bool exactOnly, const int nodeCodePoint) {
+    if (!pInfoState) {
+        return true;
+    }
+    if (exactOnly) {
+        return pInfoState->getPrimaryCodePointAt(pointIndex) == nodeCodePoint;
+    }
+    const ProximityType matchedId = pInfoState->getProximityType(pointIndex, nodeCodePoint,
+            true /* checkProximityChars */);
+    return isProximityChar(matchedId);
+}
+
+////////////////
+// Char utils //
+////////////////
+
+// TODO: Move to char_utils?
+/* static */ int DicNodeUtils::appendTwoWords(const int *const src0, const int16_t length0,
+        const int *const src1, const int16_t length1, int *dest) {
+    int actualLength0 = 0;
+    for (int i = 0; i < length0; ++i) {
+        if (src0[i] == 0) {
+            break;
+        }
+        actualLength0 = i + 1;
+    }
+    actualLength0 = min(actualLength0, MAX_WORD_LENGTH);
+    memcpy(dest, src0, actualLength0 * sizeof(dest[0]));
+    if (!src1 || length1 == 0) {
+        return actualLength0;
+    }
+    int actualLength1 = 0;
+    for (int i = 0; i < length1; ++i) {
+        if (src1[i] == 0) {
+            break;
+        }
+        actualLength1 = i + 1;
+    }
+    actualLength1 = min(actualLength1, MAX_WORD_LENGTH - actualLength0 - 1);
+    memcpy(&dest[actualLength0], src1, actualLength1 * sizeof(dest[0]));
+    return actualLength0 + actualLength1;
+}
+} // namespace latinime
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.h b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
new file mode 100644
index 0000000..15f9730
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_UTILS_H
+#define LATINIME_DIC_NODE_UTILS_H
+
+#include <stdint.h>
+#include <vector>
+
+#include "defines.h"
+#include "hash_map_compat.h"
+
+namespace latinime {
+
+class DicNode;
+class DicNodeVector;
+class ProximityInfo;
+class ProximityInfoState;
+
+class DicNodeUtils {
+ public:
+    static int appendTwoWords(const int *src0, const int16_t length0, const int *src1,
+            const int16_t length1, int *dest);
+    static void initAsRoot(const int rootPos, const uint8_t *const dicRoot,
+            const int prevWordNodePos, DicNode *newRootNode);
+    static void initAsRootWithPreviousWord(const int rootPos, const uint8_t *const dicRoot,
+            DicNode *prevWordLastNode, DicNode *newRootNode);
+    static void initByCopy(DicNode *srcNode, DicNode *destNode);
+    static void getAllChildDicNodes(DicNode *dicNode, const uint8_t *const dicRoot,
+            DicNodeVector *childDicNodes);
+    static int getWordPos(const uint8_t *const dicRoot, const int *word, const int prevWordLength);
+    static float getBigramNodeImprobability(const uint8_t *const dicRoot,
+            const DicNode *const node, hash_map_compat<int, int16_t> *const bigramCacheMap);
+    static bool isDicNodeFilteredOut(const int nodeCodePoint, const ProximityInfo *const pInfo,
+            const std::vector<int> *const codePointsFilter);
+    // TODO: Move to private
+    static void getProximityChildDicNodes(DicNode *dicNode, const uint8_t *const dicRoot,
+            const ProximityInfoState *pInfoState, const int pointIndex, bool exactOnly,
+            DicNodeVector *childDicNodes);
+
+    // TODO: Move to proximity info
+    static bool isProximityChar(ProximityType type) {
+        return type == MATCH_CHAR || type == PROXIMITY_CHAR || type == ADDITIONAL_PROXIMITY_CHAR;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodeUtils);
+    // Max cache size for the space omission error correction bigram lookup
+    static const int MAX_BIGRAM_MAP_SIZE = 20000;
+    // Max number of bigrams to look up
+    static const int MAX_BIGRAMS_CONSIDERED_PER_CONTEXT = 500;
+
+    static int getBigramNodeProbability(const uint8_t *const dicRoot, const DicNode *const node,
+            hash_map_compat<int, int16_t> *bigramCacheMap);
+    static int16_t getBigramNodeEncodedDiffProbability(const uint8_t *const dicRoot,
+            const DicNode *const node, hash_map_compat<int, int16_t> *bigramCacheMap);
+    static void createAndGetPassingChildNode(DicNode *dicNode, const ProximityInfoState *pInfoState,
+            const int pointIndex, const bool exactOnly, DicNodeVector *childDicNodes);
+    static void createAndGetAllLeavingChildNodes(DicNode *dicNode, const uint8_t *const dicRoot,
+            const ProximityInfoState *pInfoState, const int pointIndex, const bool exactOnly,
+            const std::vector<int> *const codePointsFilter,
+            const ProximityInfo *const pInfo, DicNodeVector *childDicNodes);
+    static int createAndGetLeavingChildNode(DicNode *dicNode, int pos, const uint8_t *const dicRoot,
+            const int terminalDepth, const ProximityInfoState *pInfoState, const int pointIndex,
+            const bool exactOnly, const std::vector<int> *const codePointsFilter,
+            const ProximityInfo *const pInfo, DicNodeVector *childDicNodes);
+    static int16_t getBigramProbability(const uint8_t *const dicRoot, int pos, const int nextPos,
+            hash_map_compat<int, int16_t> *bigramCacheMap);
+
+    // TODO: Move to proximity info
+    static bool isMatchedNodeCodePoint(const ProximityInfoState *pInfoState, const int pointIndex,
+            const bool exactOnly, const int nodeCodePoint);
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_UTILS_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_vector.h b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
new file mode 100644
index 0000000..ca07eda
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_VECTOR_H
+#define LATINIME_DIC_NODE_VECTOR_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dic_node.h"
+
+namespace latinime {
+
+class DicNodeVector {
+ public:
+#ifdef FLAG_DBG
+    // 0 will introduce resizing the vector.
+    static const int DEFAULT_NODES_SIZE_FOR_OPTIMIZATION = 0;
+#else
+    static const int DEFAULT_NODES_SIZE_FOR_OPTIMIZATION = 60;
+#endif
+    AK_FORCE_INLINE DicNodeVector() : mDicNodes(0), mLock(false), mEmptyNode() {}
+
+    // Specify the capacity of the vector
+    AK_FORCE_INLINE DicNodeVector(const int size) : mDicNodes(0), mLock(false), mEmptyNode() {
+        mDicNodes.reserve(size);
+    }
+
+    // Non virtual inline destructor -- never inherit this class
+    AK_FORCE_INLINE ~DicNodeVector() {}
+
+    AK_FORCE_INLINE void clear() {
+        mDicNodes.clear();
+        mLock = false;
+    }
+
+    int getSizeAndLock() {
+        mLock = true;
+        return static_cast<int>(mDicNodes.size());
+    }
+
+    bool exceeds(const size_t limit) const {
+        return mDicNodes.size() >= limit;
+    }
+
+    void pushPassingChild(DicNode *dicNode) {
+        ASSERT(!mLock);
+        mDicNodes.push_back(mEmptyNode);
+        mDicNodes.back().initAsPassingChild(dicNode);
+    }
+
+    void pushLeavingChild(DicNode *dicNode, const int pos, const uint8_t flags,
+            const int childrenPos, const int attributesPos, const int siblingPos,
+            const int nodeCodePoint, const int childrenCount, const int probability,
+            const int bigramProbability, const bool isTerminal, const bool hasMultipleChars,
+            const bool hasChildren, const uint16_t additionalSubwordLength,
+            const int *additionalSubword) {
+        ASSERT(!mLock);
+        mDicNodes.push_back(mEmptyNode);
+        mDicNodes.back().initAsChild(dicNode, pos, flags, childrenPos, attributesPos, siblingPos,
+                nodeCodePoint, childrenCount, probability, -1 /* bigramProbability */, isTerminal,
+                hasMultipleChars, hasChildren, additionalSubwordLength, additionalSubword);
+    }
+
+    DicNode *operator[](const int id) {
+        ASSERT(id < static_cast<int>(mDicNodes.size()));
+        return &mDicNodes[id];
+    }
+
+    DicNode *front() {
+        ASSERT(1 <= static_cast<int>(mDicNodes.size()));
+        return &mDicNodes[0];
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DicNodeVector);
+    std::vector<DicNode> mDicNodes;
+    bool mLock;
+    DicNode mEmptyNode;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_VECTOR_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp
new file mode 100644
index 0000000..b9a6078
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <list>
+
+#include "defines.h"
+#include "dic_node_priority_queue.h"
+#include "dic_node_utils.h"
+#include "dic_nodes_cache.h"
+
+namespace latinime {
+
+/**
+ * Truncates all of the dicNodes so that they start at the given commit point.
+ * Only called for multi-word typing input.
+ */
+DicNode *DicNodesCache::setCommitPoint(int commitPoint) {
+    std::list<DicNode> dicNodesList;
+    while (mCachedDicNodesForContinuousSuggestion->getSize() > 0) {
+        DicNode dicNode;
+        mCachedDicNodesForContinuousSuggestion->copyPop(&dicNode);
+        dicNodesList.push_front(dicNode);
+    }
+
+    // Get the starting words of the top scoring dicNode (last dicNode popped from priority queue)
+    // up to the commit point. These words have already been committed to the text view.
+    DicNode *topDicNode = &dicNodesList.front();
+    DicNode topDicNodeCopy;
+    DicNodeUtils::initByCopy(topDicNode, &topDicNodeCopy);
+
+    // Keep only those dicNodes that match the same starting words.
+    std::list<DicNode>::iterator iter;
+    for (iter = dicNodesList.begin(); iter != dicNodesList.end(); iter++) {
+        DicNode *dicNode = &*iter;
+        if (dicNode->truncateNode(&topDicNodeCopy, commitPoint)) {
+            mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
+        } else {
+            // Top dicNode should be reprocessed.
+            ASSERT(dicNode != topDicNode);
+            DicNode::managedDelete(dicNode);
+        }
+    }
+    mInputIndex -= commitPoint;
+    return topDicNode;
+}
+}  // namespace latinime
diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
new file mode 100644
index 0000000..a62aa42
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODES_CACHE_H
+#define LATINIME_DIC_NODES_CACHE_H
+
+#include <stdint.h>
+
+#include "defines.h"
+#include "dic_node_priority_queue.h"
+
+#define INITIAL_QUEUE_ID_ACTIVE 0
+#define INITIAL_QUEUE_ID_NEXT_ACTIVE 1
+#define INITIAL_QUEUE_ID_TERMINAL 2
+#define INITIAL_QUEUE_ID_CACHE_FOR_CONTINUOUS_SUGGESTION 3
+#define PRIORITY_QUEUES_SIZE 4
+
+namespace latinime {
+
+class DicNode;
+
+/**
+ * Class for controlling dicNode search priority queue and lexicon trie traversal.
+ */
+class DicNodesCache {
+ public:
+    AK_FORCE_INLINE DicNodesCache()
+            : mActiveDicNodes(&mDicNodePriorityQueues[INITIAL_QUEUE_ID_ACTIVE]),
+              mNextActiveDicNodes(&mDicNodePriorityQueues[INITIAL_QUEUE_ID_NEXT_ACTIVE]),
+              mTerminalDicNodes(&mDicNodePriorityQueues[INITIAL_QUEUE_ID_TERMINAL]),
+              mCachedDicNodesForContinuousSuggestion(
+                      &mDicNodePriorityQueues[INITIAL_QUEUE_ID_CACHE_FOR_CONTINUOUS_SUGGESTION]),
+              mInputIndex(0), mLastCachedInputIndex(0) {
+    }
+
+    AK_FORCE_INLINE virtual ~DicNodesCache() {}
+
+    AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) {
+        mInputIndex = 0;
+        mLastCachedInputIndex = 0;
+        mActiveDicNodes->reset();
+        mNextActiveDicNodes->clearAndResize(nextActiveSize);
+        mTerminalDicNodes->clearAndResize(terminalSize);
+        mCachedDicNodesForContinuousSuggestion->reset();
+    }
+
+    AK_FORCE_INLINE void continueSearch() {
+        resetTemporaryCaches();
+        restoreActiveDicNodesFromCache();
+    }
+
+    AK_FORCE_INLINE void advanceActiveDicNodes() {
+        if (DEBUG_DICT) {
+            AKLOGI("Advance active %d nodes.", mNextActiveDicNodes->getSize());
+        }
+        if (DEBUG_DICT_FULL) {
+            mNextActiveDicNodes->dump();
+        }
+        mNextActiveDicNodes =
+                moveNodesAndReturnReusableEmptyQueue(mNextActiveDicNodes, &mActiveDicNodes);
+    }
+
+    DicNode *setCommitPoint(int commitPoint);
+
+    int activeSize() const { return mActiveDicNodes->getSize(); }
+    int terminalSize() const { return mTerminalDicNodes->getSize(); }
+    bool isLookAheadCorrectionInputIndex(const int inputIndex) const {
+        return inputIndex == mInputIndex - 1;
+    }
+    void advanceInputIndex(const int inputSize) {
+        if (mInputIndex < inputSize) {
+            mInputIndex++;
+        }
+    }
+
+    AK_FORCE_INLINE void copyPushTerminal(DicNode *dicNode) {
+        mTerminalDicNodes->copyPush(dicNode);
+    }
+
+    AK_FORCE_INLINE void copyPushActive(DicNode *dicNode) {
+        mActiveDicNodes->copyPush(dicNode);
+    }
+
+    AK_FORCE_INLINE bool copyPushContinue(DicNode *dicNode) {
+        return mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
+    }
+
+    AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) {
+        DicNode *pushedDicNode = mNextActiveDicNodes->copyPush(dicNode);
+        if (!pushedDicNode) {
+            if (dicNode->isCached()) {
+                dicNode->remove();
+            }
+            // We simply drop any dic node that was not cached, ignoring the slim chance
+            // that one of its children represents what the user really wanted.
+        }
+    }
+
+    void popTerminal(DicNode *dest) {
+        mTerminalDicNodes->copyPop(dest);
+    }
+
+    void popActive(DicNode *dest) {
+        mActiveDicNodes->copyPop(dest);
+    }
+
+    bool hasCachedDicNodesForContinuousSuggestion() const {
+        return mCachedDicNodesForContinuousSuggestion
+                && mCachedDicNodesForContinuousSuggestion->getSize() > 0;
+    }
+
+    AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const {
+        // TODO: Move this variable to header
+        static const int CACHE_BACK_LENGTH = 3;
+        const int cacheInputIndex = inputSize - CACHE_BACK_LENGTH;
+        const bool shouldCache = (cacheInputIndex == mInputIndex)
+                && (cacheInputIndex != mLastCachedInputIndex);
+        return shouldCache;
+    }
+
+    AK_FORCE_INLINE void updateLastCachedInputIndex() {
+        mLastCachedInputIndex = mInputIndex;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DicNodesCache);
+
+    AK_FORCE_INLINE void restoreActiveDicNodesFromCache() {
+        if (DEBUG_DICT) {
+            AKLOGI("Restore %d nodes. inputIndex = %d.",
+                    mCachedDicNodesForContinuousSuggestion->getSize(), mLastCachedInputIndex);
+        }
+        if (DEBUG_DICT_FULL || DEBUG_CACHE) {
+            mCachedDicNodesForContinuousSuggestion->dump();
+        }
+        mInputIndex = mLastCachedInputIndex;
+        mCachedDicNodesForContinuousSuggestion =
+                moveNodesAndReturnReusableEmptyQueue(
+                        mCachedDicNodesForContinuousSuggestion, &mActiveDicNodes);
+    }
+
+    AK_FORCE_INLINE static DicNodePriorityQueue *moveNodesAndReturnReusableEmptyQueue(
+            DicNodePriorityQueue *src, DicNodePriorityQueue **dest) {
+        const int srcMaxSize = src->getMaxSize();
+        const int destMaxSize = (*dest)->getMaxSize();
+        DicNodePriorityQueue *tmp = *dest;
+        *dest = src;
+        (*dest)->setMaxSize(destMaxSize);
+        tmp->clearAndResize(srcMaxSize);
+        return tmp;
+    }
+
+    AK_FORCE_INLINE void resetTemporaryCaches() {
+        mActiveDicNodes->clear();
+        mNextActiveDicNodes->clear();
+        mTerminalDicNodes->clear();
+    }
+
+    DicNodePriorityQueue mDicNodePriorityQueues[PRIORITY_QUEUES_SIZE];
+    // Active dicNodes currently being expanded.
+    DicNodePriorityQueue *mActiveDicNodes;
+    // Next dicNodes to be expanded.
+    DicNodePriorityQueue *mNextActiveDicNodes;
+    // Current top terminal dicNodes.
+    DicNodePriorityQueue *mTerminalDicNodes;
+    // Cached dicNodes used for continuous suggestion.
+    DicNodePriorityQueue *mCachedDicNodesForContinuousSuggestion;
+    int mInputIndex;
+    int mLastCachedInputIndex;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODES_CACHE_H
diff --git a/native/jni/src/suggest/core/dictionary/shortcut_utils.h b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
new file mode 100644
index 0000000..c411408
--- /dev/null
+++ b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_SHORTCUT_UTILS
+#define LATINIME_SHORTCUT_UTILS
+
+#include "defines.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "terminal_attributes.h"
+
+namespace latinime {
+
+class ShortcutUtils {
+ public:
+    static int outputShortcuts(const TerminalAttributes *const terminalAttributes,
+            int outputWordIndex, const int finalScore, int *const outputCodePoints,
+            int *const frequencies, int *const outputTypes, const bool sameAsTyped) {
+        TerminalAttributes::ShortcutIterator iterator = terminalAttributes->getShortcutIterator();
+        while (iterator.hasNextShortcutTarget() && outputWordIndex < MAX_RESULTS) {
+            int shortcutTarget[MAX_WORD_LENGTH];
+            int shortcutProbability;
+            const int shortcutTargetStringLength = iterator.getNextShortcutTarget(
+                    MAX_WORD_LENGTH, shortcutTarget, &shortcutProbability);
+            int shortcutScore;
+            int kind;
+            if (shortcutProbability == BinaryFormat::WHITELIST_SHORTCUT_PROBABILITY
+                    && sameAsTyped) {
+                shortcutScore = S_INT_MAX;
+                kind = Dictionary::KIND_WHITELIST;
+            } else {
+                // shortcut entry's score == its base entry's score - 1
+                shortcutScore = finalScore;
+                // Protection against int underflow
+                shortcutScore = max(S_INT_MIN + 1, shortcutScore) - 1;
+                kind = Dictionary::KIND_CORRECTION;
+            }
+            outputTypes[outputWordIndex] = kind;
+            frequencies[outputWordIndex] = shortcutScore;
+            frequencies[outputWordIndex] = max(S_INT_MIN + 1, shortcutScore) - 1;
+            const int startIndex2 = outputWordIndex * MAX_WORD_LENGTH;
+            DicNodeUtils::appendTwoWords(0, 0, shortcutTarget, shortcutTargetStringLength,
+                    &outputCodePoints[startIndex2]);
+            ++outputWordIndex;
+        }
+        return outputWordIndex;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ShortcutUtils);
+};
+} // namespace latinime
+#endif // LATINIME_SHORTCUT_UTILS
diff --git a/native/jni/src/suggest/core/policy/scoring.h b/native/jni/src/suggest/core/policy/scoring.h
new file mode 100644
index 0000000..b8c10e2
--- /dev/null
+++ b/native/jni/src/suggest/core/policy/scoring.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_SCORING_H
+#define LATINIME_SCORING_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class DicNode;
+class DicTraverseSession;
+
+// This class basically tweaks suggestions and distances apart from CompoundDistance
+class Scoring {
+ public:
+    virtual int calculateFinalScore(const float compoundDistance, const int inputSize,
+            const bool forceCommit) const = 0;
+    virtual bool getMostProbableString(
+            const DicTraverseSession *const traverseSession, const int terminalSize,
+            const float languageWeight, int *const outputCodePoints, int *const type,
+            int *const freq) const = 0;
+    virtual void safetyNetForMostProbableString(const int terminalSize,
+            const int maxScore, int *const outputCodePoints, int *const frequencies) const = 0;
+    // TODO: Make more generic
+    virtual void searchWordWithDoubleLetter(DicNode *terminals,
+            const int terminalSize, int *doubleLetterTerminalIndex,
+            DoubleLetterLevel *doubleLetterLevel) const = 0;
+    virtual float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
+            DicNode *const terminals, const int size) const = 0;
+    virtual float getDoubleLetterDemotionDistanceCost(const int terminalIndex,
+            const int doubleLetterTerminalIndex,
+            const DoubleLetterLevel doubleLetterLevel) const = 0;
+    virtual bool doesAutoCorrectValidWord() const = 0;
+
+ protected:
+    Scoring() {}
+    virtual ~Scoring() {}
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Scoring);
+};
+} // namespace latinime
+#endif // LATINIME_SCORING_H
diff --git a/native/jni/src/suggest/core/policy/suggest_policy.h b/native/jni/src/suggest/core/policy/suggest_policy.h
new file mode 100644
index 0000000..885e214
--- /dev/null
+++ b/native/jni/src/suggest/core/policy/suggest_policy.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_SUGGEST_POLICY_H
+#define LATINIME_SUGGEST_POLICY_H
+
+#include "defines.h"
+
+namespace latinime {
+class Traversal;
+class Scoring;
+class Weighting;
+
+class SuggestPolicy {
+ public:
+    SuggestPolicy() {}
+    virtual ~SuggestPolicy() {}
+    virtual const Traversal *getTraversal() const = 0;
+    virtual const Scoring *getScoring() const = 0;
+    virtual const Weighting *getWeighting() const = 0;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(SuggestPolicy);
+};
+} // namespace latinime
+#endif // LATINIME_SUGGEST_POLICY_H
diff --git a/native/jni/src/suggest/core/policy/traversal.h b/native/jni/src/suggest/core/policy/traversal.h
new file mode 100644
index 0000000..02c358a
--- /dev/null
+++ b/native/jni/src/suggest/core/policy/traversal.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_TRAVERSAL_H
+#define LATINIME_TRAVERSAL_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class DicTraverseSession;
+
+class Traversal {
+ public:
+    virtual int getMaxPointerCount() const = 0;
+    virtual bool allowsErrorCorrections(const DicNode *const dicNode) const = 0;
+    virtual bool isOmission(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode, const DicNode *const childDicNode) const = 0;
+    virtual bool isSpaceSubstitutionTerminal(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const = 0;
+    virtual bool isSpaceOmissionTerminal(const DicTraverseSession *const traverseSession,
+               const DicNode *const dicNode) const = 0;
+    virtual bool shouldDepthLevelCache(const DicTraverseSession *const traverseSession) const = 0;
+    virtual bool shouldNodeLevelCache(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const = 0;
+    virtual bool canDoLookAheadCorrection(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const = 0;
+    virtual ProximityType getProximityType(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+            const DicNode *const childDicNode) const = 0;
+    virtual bool sameAsTyped(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const = 0;
+    virtual bool needsToTraverseAllUserInput() const = 0;
+    virtual float getMaxSpatialDistance() const = 0;
+    virtual bool allowPartialCommit() const = 0;
+    virtual int getDefaultExpandDicNodeSize() const = 0;
+    virtual int getMaxCacheSize() const = 0;
+    virtual bool isPossibleOmissionChildNode(
+            const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
+            const DicNode *const dicNode) const = 0;
+    virtual bool isGoodToTraverseNextWord(const DicNode *const dicNode) const = 0;
+
+ protected:
+    Traversal() {}
+    virtual ~Traversal() {}
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Traversal);
+};
+} // namespace latinime
+#endif // LATINIME_TRAVERSAL_H
diff --git a/native/jni/src/suggest/core/policy/weighting.cpp b/native/jni/src/suggest/core/policy/weighting.cpp
new file mode 100644
index 0000000..e62b704
--- /dev/null
+++ b/native/jni/src/suggest/core/policy/weighting.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "suggest/core/policy/weighting.h"
+
+#include "char_utils.h"
+#include "defines.h"
+#include "hash_map_compat.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_profiler.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/session/dic_traverse_session.h"
+
+namespace latinime {
+
+static inline void profile(const CorrectionType correctionType, DicNode *const node) {
+#if DEBUG_DICT
+    switch (correctionType) {
+    case CT_OMISSION:
+        PROF_OMISSION(node->mProfiler);
+        return;
+    case CT_ADDITIONAL_PROXIMITY:
+        PROF_ADDITIONAL_PROXIMITY(node->mProfiler);
+        return;
+    case CT_SUBSTITUTION:
+        PROF_SUBSTITUTION(node->mProfiler);
+        return;
+    case CT_NEW_WORD:
+        PROF_NEW_WORD(node->mProfiler);
+        return;
+    case CT_MATCH:
+        PROF_MATCH(node->mProfiler);
+        return;
+    case CT_COMPLETION:
+        PROF_COMPLETION(node->mProfiler);
+        return;
+    case CT_TERMINAL:
+        PROF_TERMINAL(node->mProfiler);
+        return;
+    case CT_SPACE_SUBSTITUTION:
+        PROF_SPACE_SUBSTITUTION(node->mProfiler);
+        return;
+    case CT_INSERTION:
+        PROF_INSERTION(node->mProfiler);
+        return;
+    case CT_TRANSPOSITION:
+        PROF_TRANSPOSITION(node->mProfiler);
+        return;
+    default:
+        // do nothing
+        return;
+    }
+#else
+    // do nothing
+#endif
+}
+
+/* static */ void Weighting::addCostAndForwardInputIndex(const Weighting *const weighting,
+        const CorrectionType correctionType,
+        const DicTraverseSession *const traverseSession,
+        const DicNode *const parentDicNode, DicNode *const dicNode,
+        hash_map_compat<int, int16_t> *const bigramCacheMap) {
+    const int inputSize = traverseSession->getInputSize();
+    DicNode_InputStateG inputStateG;
+    inputStateG.mNeedsToUpdateInputStateG = false; // Don't use input info by default
+    const float spatialCost = Weighting::getSpatialCost(weighting, correctionType,
+            traverseSession, parentDicNode, dicNode, &inputStateG);
+    const float languageCost = Weighting::getLanguageCost(weighting, correctionType,
+            traverseSession, parentDicNode, dicNode, bigramCacheMap);
+    const bool edit = Weighting::isEditCorrection(correctionType);
+    const bool proximity = Weighting::isProximityCorrection(weighting, correctionType,
+            traverseSession, dicNode);
+    profile(correctionType, dicNode);
+    if (inputStateG.mNeedsToUpdateInputStateG) {
+        dicNode->updateInputIndexG(&inputStateG);
+    } else {
+        dicNode->forwardInputIndex(0, getForwardInputCount(correctionType),
+                (correctionType == CT_TRANSPOSITION));
+    }
+    dicNode->addCost(spatialCost, languageCost, weighting->needsToNormalizeCompoundDistance(),
+            inputSize, edit, proximity);
+}
+
+/* static */ float Weighting::getSpatialCost(const Weighting *const weighting,
+        const CorrectionType correctionType,
+        const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
+        const DicNode *const dicNode, DicNode_InputStateG *const inputStateG) {
+    switch(correctionType) {
+    case CT_OMISSION:
+        return weighting->getOmissionCost(parentDicNode, dicNode);
+    case CT_ADDITIONAL_PROXIMITY:
+        // only used for typing
+        return weighting->getAdditionalProximityCost();
+    case CT_SUBSTITUTION:
+        // only used for typing
+        return weighting->getSubstitutionCost();
+    case CT_NEW_WORD:
+        return weighting->getNewWordCost(dicNode);
+    case CT_MATCH:
+        return weighting->getMatchedCost(traverseSession, dicNode, inputStateG);
+    case CT_COMPLETION:
+        return weighting->getCompletionCost(traverseSession, dicNode);
+    case CT_TERMINAL:
+        return weighting->getTerminalSpatialCost(traverseSession, dicNode);
+    case CT_SPACE_SUBSTITUTION:
+        return weighting->getSpaceSubstitutionCost();
+    case CT_INSERTION:
+        return weighting->getInsertionCost(traverseSession, parentDicNode, dicNode);
+    case CT_TRANSPOSITION:
+        return weighting->getTranspositionCost(traverseSession, parentDicNode, dicNode);
+    default:
+        return 0.0f;
+    }
+}
+
+/* static */ float Weighting::getLanguageCost(const Weighting *const weighting,
+        const CorrectionType correctionType, const DicTraverseSession *const traverseSession,
+        const DicNode *const parentDicNode, const DicNode *const dicNode,
+        hash_map_compat<int, int16_t> *const bigramCacheMap) {
+    switch(correctionType) {
+    case CT_OMISSION:
+        return 0.0f;
+    case CT_SUBSTITUTION:
+        return 0.0f;
+    case CT_NEW_WORD:
+        return weighting->getNewWordBigramCost(traverseSession, parentDicNode, bigramCacheMap);
+    case CT_MATCH:
+        return 0.0f;
+    case CT_COMPLETION:
+        return 0.0f;
+    case CT_TERMINAL: {
+        const float languageImprobability =
+                DicNodeUtils::getBigramNodeImprobability(
+                        traverseSession->getOffsetDict(), dicNode, bigramCacheMap);
+        return weighting->getTerminalLanguageCost(traverseSession, dicNode, languageImprobability);
+    }
+    case CT_SPACE_SUBSTITUTION:
+        return 0.0f;
+    case CT_INSERTION:
+        return 0.0f;
+    case CT_TRANSPOSITION:
+        return 0.0f;
+    default:
+        return 0.0f;
+    }
+}
+
+/* static */ bool Weighting::isEditCorrection(const CorrectionType correctionType) {
+    switch(correctionType) {
+        case CT_OMISSION:
+            return true;
+        case CT_ADDITIONAL_PROXIMITY:
+            // Should return true?
+            return false;
+        case CT_SUBSTITUTION:
+            // Should return true?
+            return false;
+        case CT_NEW_WORD:
+            return false;
+        case CT_MATCH:
+            return false;
+        case CT_COMPLETION:
+            return false;
+        case CT_TERMINAL:
+            return false;
+        case CT_SPACE_SUBSTITUTION:
+            return false;
+        case CT_INSERTION:
+            return true;
+        case CT_TRANSPOSITION:
+            return true;
+        default:
+            return false;
+    }
+}
+
+/* static */ bool Weighting::isProximityCorrection(const Weighting *const weighting,
+        const CorrectionType correctionType,
+        const DicTraverseSession *const traverseSession, const DicNode *const dicNode) {
+    switch(correctionType) {
+        case CT_OMISSION:
+            return false;
+        case CT_ADDITIONAL_PROXIMITY:
+            return false;
+        case CT_SUBSTITUTION:
+            return false;
+        case CT_NEW_WORD:
+            return false;
+        case CT_MATCH:
+            return weighting->isProximityDicNode(traverseSession, dicNode);
+        case CT_COMPLETION:
+            return false;
+        case CT_TERMINAL:
+            return false;
+        case CT_SPACE_SUBSTITUTION:
+            return false;
+        case CT_INSERTION:
+            return false;
+        case CT_TRANSPOSITION:
+            return false;
+        default:
+            return false;
+    }
+}
+
+/* static */ int Weighting::getForwardInputCount(const CorrectionType correctionType) {
+    switch(correctionType) {
+        case CT_OMISSION:
+            return 0;
+        case CT_ADDITIONAL_PROXIMITY:
+            return 0;
+        case CT_SUBSTITUTION:
+            return 0;
+        case CT_NEW_WORD:
+            return 0;
+        case CT_MATCH:
+            return 1;
+        case CT_COMPLETION:
+            return 0;
+        case CT_TERMINAL:
+            return 0;
+        case CT_SPACE_SUBSTITUTION:
+            return 1;
+        case CT_INSERTION:
+            return 2;
+        case CT_TRANSPOSITION:
+            return 2;
+        default:
+            return 0;
+    }
+}
+}  // namespace latinime
diff --git a/native/jni/src/suggest/core/policy/weighting.h b/native/jni/src/suggest/core/policy/weighting.h
new file mode 100644
index 0000000..b92dbe2
--- /dev/null
+++ b/native/jni/src/suggest/core/policy/weighting.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_WEIGHTING_H
+#define LATINIME_WEIGHTING_H
+
+#include "defines.h"
+#include "hash_map_compat.h"
+
+namespace latinime {
+
+class DicNode;
+class DicTraverseSession;
+struct DicNode_InputStateG;
+
+class Weighting {
+ public:
+    static void addCostAndForwardInputIndex(const Weighting *const weighting,
+            const CorrectionType correctionType,
+            const DicTraverseSession *const traverseSession,
+            const DicNode *const parentDicNode, DicNode *const dicNode,
+            hash_map_compat<int, int16_t> *const bigramCacheMap);
+
+ protected:
+    virtual float getTerminalSpatialCost(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const = 0;
+
+    virtual float getOmissionCost(
+         const DicNode *const parentDicNode, const DicNode *const dicNode) const = 0;
+
+    virtual float getMatchedCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+            DicNode_InputStateG *inputStateG) const = 0;
+
+    virtual bool isProximityDicNode(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const = 0;
+
+    virtual float getTranspositionCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
+            const DicNode *const dicNode) const = 0;
+
+    virtual float getInsertionCost(
+            const DicTraverseSession *const traverseSession,
+            const DicNode *const parentDicNode, const DicNode *const dicNode) const = 0;
+
+    virtual float getNewWordCost(const DicNode *const dicNode) const = 0;
+
+    virtual float getNewWordBigramCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+            hash_map_compat<int, int16_t> *const bigramCacheMap) const = 0;
+
+    virtual float getCompletionCost(
+            const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const = 0;
+
+    virtual float getTerminalLanguageCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+            float dicNodeLanguageImprobability) const = 0;
+
+    virtual bool needsToNormalizeCompoundDistance() const = 0;
+
+    virtual float getAdditionalProximityCost() const = 0;
+
+    virtual float getSubstitutionCost() const = 0;
+
+    virtual float getSpaceSubstitutionCost() const = 0;
+
+    Weighting() {}
+    virtual ~Weighting() {}
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Weighting);
+
+    static float getSpatialCost(const Weighting *const weighting,
+            const CorrectionType correctionType, const DicTraverseSession *const traverseSession,
+            const DicNode *const parentDicNode, const DicNode *const dicNode,
+            DicNode_InputStateG *const inputStateG);
+    static float getLanguageCost(const Weighting *const weighting,
+            const CorrectionType correctionType, const DicTraverseSession *const traverseSession,
+            const DicNode *const parentDicNode, const DicNode *const dicNode,
+            hash_map_compat<int, int16_t> *const bigramCacheMap);
+    // TODO: Move to TypingWeighting and GestureWeighting?
+    static bool isEditCorrection(const CorrectionType correctionType);
+    // TODO: Move to TypingWeighting and GestureWeighting?
+    static bool isProximityCorrection(const Weighting *const weighting,
+            const CorrectionType correctionType, const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode);
+    // TODO: Move to TypingWeighting and GestureWeighting?
+    static int getForwardInputCount(const CorrectionType correctionType);
+};
+} // namespace latinime
+#endif // LATINIME_WEIGHTING_H
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
new file mode 100644
index 0000000..5b783a2
--- /dev/null
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "suggest/core/session/dic_traverse_session.h"
+
+#include "defines.h"
+#include "dictionary.h"
+#include "dic_traverse_wrapper.h"
+#include "jni.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+
+namespace latinime {
+
+const int DicTraverseSession::CACHE_START_INPUT_LENGTH_THRESHOLD = 20;
+
+// A factory method for DicTraverseSession
+static void *getSessionInstance(JNIEnv *env, jstring localeStr) {
+    return new DicTraverseSession(env, localeStr);
+}
+
+// TODO: Pass "DicTraverseSession *traverseSession" when the source code structure settles down.
+static void initSessionInstance(void *traverseSession, const Dictionary *const dictionary,
+        const int *prevWord, const int prevWordLength) {
+    if (traverseSession) {
+        DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
+        tSession->init(dictionary, prevWord, prevWordLength);
+    }
+}
+
+// TODO: Pass "DicTraverseSession *traverseSession" when the source code structure settles down.
+static void releaseSessionInstance(void *traverseSession) {
+    delete static_cast<DicTraverseSession *>(traverseSession);
+}
+
+// An ad-hoc internal class to register the factory method defined above
+class TraverseSessionFactoryRegisterer {
+ public:
+    TraverseSessionFactoryRegisterer() {
+        DicTraverseWrapper::setTraverseSessionFactoryMethod(getSessionInstance);
+        DicTraverseWrapper::setTraverseSessionInitMethod(initSessionInstance);
+        DicTraverseWrapper::setTraverseSessionReleaseMethod(releaseSessionInstance);
+    }
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TraverseSessionFactoryRegisterer);
+};
+
+// To invoke the TraverseSessionFactoryRegisterer constructor in the global constructor.
+static TraverseSessionFactoryRegisterer traverseSessionFactoryRegisterer;
+
+void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
+        int prevWordLength) {
+    mDictionary = dictionary;
+    if (!prevWord) {
+        mPrevWordPos = NOT_VALID_WORD;
+        return;
+    }
+    mPrevWordPos = DicNodeUtils::getWordPos(dictionary->getOffsetDict(), prevWord, prevWordLength);
+}
+
+void DicTraverseSession::setupForGetSuggestions(const ProximityInfo *pInfo,
+        const int *inputCodePoints, const int inputSize, const int *const inputXs,
+        const int *const inputYs, const int *const times, const int *const pointerIds,
+        const float maxSpatialDistance, const int maxPointerCount) {
+    mProximityInfo = pInfo;
+    mMaxPointerCount = maxPointerCount;
+    initializeProximityInfoStates(inputCodePoints, inputXs, inputYs, times, pointerIds, inputSize,
+            maxSpatialDistance, maxPointerCount);
+}
+
+const uint8_t *DicTraverseSession::getOffsetDict() const {
+    return mDictionary->getOffsetDict();
+}
+
+int DicTraverseSession::getDictFlags() const {
+    return mDictionary->getDictFlags();
+}
+
+void DicTraverseSession::resetCache(const int nextActiveCacheSize, const int maxWords) {
+    mDicNodesCache.reset(nextActiveCacheSize, maxWords);
+    mBigramCacheMap.clear();
+    mPartiallyCommited = false;
+}
+
+void DicTraverseSession::initializeProximityInfoStates(const int *const inputCodePoints,
+        const int *const inputXs, const int *const inputYs, const int *const times,
+        const int *const pointerIds, const int inputSize, const float maxSpatialDistance,
+        const int maxPointerCount) {
+    ASSERT(1 <= maxPointerCount && maxPointerCount <= MAX_POINTER_COUNT_G);
+    mInputSize = 0;
+    for (int i = 0; i < maxPointerCount; ++i) {
+        mProximityInfoStates[i].initInputParams(i, maxSpatialDistance, getProximityInfo(),
+                inputCodePoints, inputSize, inputXs, inputYs, times, pointerIds,
+                maxPointerCount == MAX_POINTER_COUNT_G
+                /* TODO: this is a hack. fix proximity info state */);
+        mInputSize += mProximityInfoStates[i].size();
+    }
+}
+} // namespace latinime
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
new file mode 100644
index 0000000..525d198
--- /dev/null
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_TRAVERSE_SESSION_H
+#define LATINIME_DIC_TRAVERSE_SESSION_H
+
+#include <stdint.h>
+#include <vector>
+
+#include "defines.h"
+#include "hash_map_compat.h"
+#include "jni.h"
+#include "proximity_info_state.h"
+#include "suggest/core/dicnode/dic_nodes_cache.h"
+
+namespace latinime {
+
+class Dictionary;
+class ProximityInfo;
+
+class DicTraverseSession {
+ public:
+    AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr)
+            : mPrevWordPos(NOT_VALID_WORD), mProximityInfo(0),
+              mDictionary(0), mDicNodesCache(), mBigramCacheMap(),
+              mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1) {
+        // NOTE: mProximityInfoStates is an array of instances.
+        // No need to initialize it explicitly here.
+    }
+
+    // Non virtual inline destructor -- never inherit this class
+    AK_FORCE_INLINE ~DicTraverseSession() {}
+
+    void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength);
+    // TODO: Remove and merge into init
+    void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
+            const int inputSize, const int *const inputXs, const int *const inputYs,
+            const int *const times, const int *const pointerIds, const float maxSpatialDistance,
+            const int maxPointerCount);
+    void resetCache(const int nextActiveCacheSize, const int maxWords);
+
+    const uint8_t *getOffsetDict() const;
+    int getDictFlags() const;
+
+    //--------------------
+    // getters and setters
+    //--------------------
+    const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
+    int getPrevWordPos() const { return mPrevWordPos; }
+    // TODO: REMOVE
+    void setPrevWordPos(int pos) { mPrevWordPos = pos; }
+    // TODO: Use proper parameter when changed
+    int getDicRootPos() const { return 0; }
+    DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
+    hash_map_compat<int, int16_t> *getBigramCacheMap() { return &mBigramCacheMap; }
+    const ProximityInfoState *getProximityInfoState(int id) const {
+        return &mProximityInfoStates[id];
+    }
+    int getInputSize() const { return mInputSize; }
+    void setPartiallyCommited() { mPartiallyCommited = true; }
+    bool isPartiallyCommited() const { return mPartiallyCommited; }
+
+    bool isOnlyOnePointerUsed(int *pointerId) const {
+        // Not in the dictionary word
+        int usedPointerCount = 0;
+        int usedPointerId = 0;
+        for (int i = 0; i < mMaxPointerCount; ++i) {
+            if (mProximityInfoStates[i].isUsed()) {
+                ++usedPointerCount;
+                usedPointerId = i;
+            }
+        }
+        if (usedPointerCount != 1) {
+            return false;
+        }
+        *pointerId = usedPointerId;
+        return true;
+    }
+
+    void getSearchKeys(const DicNode *node, std::vector<int> *const outputSearchKeyVector) const {
+        for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
+            if (!mProximityInfoStates[i].isUsed()) {
+                continue;
+            }
+            const int pointerId = node->getInputIndex(i);
+            const std::vector<int> *const searchKeyVector =
+                    mProximityInfoStates[i].getSearchKeyVector(pointerId);
+            outputSearchKeyVector->insert(outputSearchKeyVector->end(), searchKeyVector->begin(),
+                    searchKeyVector->end());
+        }
+    }
+
+    ProximityType getProximityTypeG(const DicNode *const node, const int childCodePoint) const {
+        ProximityType proximityType = UNRELATED_CHAR;
+        for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
+            if (!mProximityInfoStates[i].isUsed()) {
+                continue;
+            }
+            const int pointerId = node->getInputIndex(i);
+            proximityType = mProximityInfoStates[i].getProximityTypeG(pointerId, childCodePoint);
+            ASSERT(proximityType == UNRELATED_CHAR || proximityType == MATCH_CHAR);
+            // TODO: Make this more generic
+            // Currently we assume there are only two types here -- UNRELATED_CHAR
+            // and MATCH_CHAR
+            if (proximityType != UNRELATED_CHAR) {
+                return proximityType;
+            }
+        }
+        return proximityType;
+    }
+
+    AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const {
+        return mDicNodesCache.isCacheBorderForTyping(inputSize);
+    }
+
+    /**
+     * Returns whether or not it is possible to continue suggestion from the previous search.
+     */
+    // TODO: Remove. No need to check once the session is fully implemented.
+    bool isContinuousSuggestionPossible() const {
+        if (!mDicNodesCache.hasCachedDicNodesForContinuousSuggestion()) {
+            return false;
+        }
+        ASSERT(mMaxPointerCount < MAX_POINTER_COUNT_G);
+        for (int i = 0; i < mMaxPointerCount; ++i) {
+            const ProximityInfoState *const pInfoState = getProximityInfoState(i);
+            // If a proximity info state is not continuous suggestion possible,
+            // do not continue searching.
+            if (pInfoState->isUsed() && !pInfoState->isContinuousSuggestionPossible()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
+    // threshold to start caching
+    static const int CACHE_START_INPUT_LENGTH_THRESHOLD;
+    void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs,
+            const int *const inputYs, const int *const times, const int *const pointerIds,
+            const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
+
+    int mPrevWordPos;
+    const ProximityInfo *mProximityInfo;
+    const Dictionary *mDictionary;
+
+    DicNodesCache mDicNodesCache;
+    // Temporary cache for bigram frequencies
+    hash_map_compat<int, int16_t> mBigramCacheMap;
+    ProximityInfoState mProximityInfoStates[MAX_POINTER_COUNT_G];
+
+    int mInputSize;
+    bool mPartiallyCommited;
+    int mMaxPointerCount;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_TRAVERSE_SESSION_H
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
new file mode 100644
index 0000000..764c372
--- /dev/null
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "suggest/core/suggest.h"
+
+#include "char_utils.h"
+#include "dictionary.h"
+#include "proximity_info.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_priority_queue.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/dictionary/shortcut_utils.h"
+#include "suggest/core/policy/scoring.h"
+#include "suggest/core/policy/traversal.h"
+#include "suggest/core/policy/weighting.h"
+#include "suggest/core/session/dic_traverse_session.h"
+#include "terminal_attributes.h"
+
+namespace latinime {
+
+// Initialization of class constants.
+const int Suggest::LOOKAHEAD_DIC_NODES_CACHE_SIZE = 25;
+const int Suggest::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16;
+const int Suggest::MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE = 2;
+const float Suggest::AUTOCORRECT_CLASSIFICATION_THRESHOLD = 0.33f;
+const float Suggest::AUTOCORRECT_LANGUAGE_FEATURE_THRESHOLD = 0.6f;
+
+const bool Suggest::CORRECT_SPACE_OMISSION = true;
+const bool Suggest::CORRECT_TRANSPOSITION = true;
+const bool Suggest::CORRECT_INSERTION = true;
+const bool Suggest::CORRECT_OMISSION_G = true;
+
+/**
+ * Returns a set of suggestions for the given input touch points. The commitPoint argument indicates
+ * whether to prematurely commit the suggested words up to the given point for sentence-level
+ * suggestion.
+ *
+ * Note: Currently does not support concurrent calls across threads. Continuous suggestion is
+ * automatically activated for sequential calls that share the same starting input.
+ * TODO: Stop detecting continuous suggestion. Start using traverseSession instead.
+ */
+int Suggest::getSuggestions(ProximityInfo *pInfo, void *traverseSession,
+        int *inputXs, int *inputYs, int *times, int *pointerIds, int *inputCodePoints,
+        int inputSize, int commitPoint, int *outWords, int *frequencies, int *outputIndices,
+        int *outputTypes) const {
+    PROF_OPEN;
+    PROF_START(0);
+    const float maxSpatialDistance = TRAVERSAL->getMaxSpatialDistance();
+    DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
+    tSession->setupForGetSuggestions(pInfo, inputCodePoints, inputSize, inputXs, inputYs, times,
+            pointerIds, maxSpatialDistance, TRAVERSAL->getMaxPointerCount());
+    // TODO: Add the way to evaluate cache
+
+    initializeSearch(tSession, commitPoint);
+    PROF_END(0);
+    PROF_START(1);
+
+    // keep expanding search dicNodes until all have terminated.
+    while (tSession->getDicTraverseCache()->activeSize() > 0) {
+        expandCurrentDicNodes(tSession);
+        tSession->getDicTraverseCache()->advanceActiveDicNodes();
+        tSession->getDicTraverseCache()->advanceInputIndex(inputSize);
+    }
+    PROF_END(1);
+    PROF_START(2);
+    const int size = outputSuggestions(tSession, frequencies, outWords, outputIndices, outputTypes);
+    PROF_END(2);
+    PROF_CLOSE;
+    return size;
+}
+
+/**
+ * Initializes the search at the root of the lexicon trie. Note that when possible the search will
+ * continue suggestion from where it left off during the last call.
+ */
+void Suggest::initializeSearch(DicTraverseSession *traverseSession, int commitPoint) const {
+    if (!traverseSession->getProximityInfoState(0)->isUsed()) {
+        return;
+    }
+    if (TRAVERSAL->allowPartialCommit()) {
+        commitPoint = 0;
+    }
+
+    if (traverseSession->getInputSize() > MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE
+            && traverseSession->isContinuousSuggestionPossible()) {
+        if (commitPoint == 0) {
+            // Continue suggestion
+            traverseSession->getDicTraverseCache()->continueSearch();
+        } else {
+            // Continue suggestion after partial commit.
+            DicNode *topDicNode =
+                    traverseSession->getDicTraverseCache()->setCommitPoint(commitPoint);
+            traverseSession->setPrevWordPos(topDicNode->getPrevWordNodePos());
+            traverseSession->getDicTraverseCache()->continueSearch();
+            traverseSession->setPartiallyCommited();
+        }
+    } else {
+        // Restart recognition at the root.
+        traverseSession->resetCache(TRAVERSAL->getMaxCacheSize(), MAX_RESULTS);
+        // Create a new dic node here
+        DicNode rootNode;
+        DicNodeUtils::initAsRoot(traverseSession->getDicRootPos(),
+                traverseSession->getOffsetDict(), traverseSession->getPrevWordPos(), &rootNode);
+        traverseSession->getDicTraverseCache()->copyPushActive(&rootNode);
+    }
+}
+
+/**
+ * Outputs the final list of suggestions (i.e., terminal nodes).
+ */
+int Suggest::outputSuggestions(DicTraverseSession *traverseSession, int *frequencies,
+        int *outputCodePoints, int *spaceIndices, int *outputTypes) const {
+    const int terminalSize = min(MAX_RESULTS,
+            static_cast<int>(traverseSession->getDicTraverseCache()->terminalSize()));
+    DicNode terminals[MAX_RESULTS]; // Avoiding non-POD variable length array
+
+    for (int index = terminalSize - 1; index >= 0; --index) {
+        traverseSession->getDicTraverseCache()->popTerminal(&terminals[index]);
+    }
+
+    const float languageWeight = SCORING->getAdjustedLanguageWeight(
+            traverseSession, terminals, terminalSize);
+
+    int outputWordIndex = 0;
+    // Insert most probable word at index == 0 as long as there is one terminal at least
+    const bool hasMostProbableString =
+            SCORING->getMostProbableString(traverseSession, terminalSize, languageWeight,
+                    &outputCodePoints[0], &outputTypes[0], &frequencies[0]);
+    if (hasMostProbableString) {
+        ++outputWordIndex;
+    }
+
+    // Initial value of the loop index for terminal nodes (words)
+    int doubleLetterTerminalIndex = -1;
+    DoubleLetterLevel doubleLetterLevel = NOT_A_DOUBLE_LETTER;
+    SCORING->searchWordWithDoubleLetter(terminals, terminalSize,
+            &doubleLetterTerminalIndex, &doubleLetterLevel);
+
+    int maxScore = S_INT_MIN;
+    // Output suggestion results here
+    for (int terminalIndex = 0; terminalIndex < terminalSize && outputWordIndex < MAX_RESULTS;
+            ++terminalIndex) {
+        DicNode *terminalDicNode = &terminals[terminalIndex];
+        if (DEBUG_GEO_FULL) {
+            terminalDicNode->dump("OUT:");
+        }
+        const float doubleLetterCost = SCORING->getDoubleLetterDemotionDistanceCost(
+                terminalIndex, doubleLetterTerminalIndex, doubleLetterLevel);
+        const float compoundDistance = terminalDicNode->getCompoundDistance(languageWeight)
+                + doubleLetterCost;
+        const TerminalAttributes terminalAttributes(traverseSession->getOffsetDict(),
+                terminalDicNode->getFlags(), terminalDicNode->getAttributesPos());
+        const int originalTerminalProbability = terminalDicNode->getProbability();
+
+        // Do not suggest words with a 0 probability, or entries that are blacklisted or do not
+        // represent a word. However, we should still submit their shortcuts if any.
+        const bool isValidWord =
+                originalTerminalProbability > 0 && !terminalAttributes.isBlacklistedOrNotAWord();
+        // Increase output score of top typing suggestion to ensure autocorrection.
+        // TODO: Better integration with java side autocorrection logic.
+        // Force autocorrection for obvious long multi-word suggestions.
+        const bool isForceCommitMultiWords = TRAVERSAL->allowPartialCommit()
+                && (traverseSession->isPartiallyCommited()
+                        || (traverseSession->getInputSize() >= MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT
+                                && terminalDicNode->hasMultipleWords()));
+
+        const int finalScore = SCORING->calculateFinalScore(
+                compoundDistance, traverseSession->getInputSize(),
+                isForceCommitMultiWords || (isValidWord && SCORING->doesAutoCorrectValidWord()));
+
+        maxScore = max(maxScore, finalScore);
+
+        if (TRAVERSAL->allowPartialCommit()) {
+            // Index for top typing suggestion should be 0.
+            if (isValidWord && outputWordIndex == 0) {
+                terminalDicNode->outputSpacePositionsResult(spaceIndices);
+            }
+        }
+
+        // Do not suggest words with a 0 probability, or entries that are blacklisted or do not
+        // represent a word. However, we should still submit their shortcuts if any.
+        if (isValidWord) {
+            outputTypes[outputWordIndex] = Dictionary::KIND_CORRECTION;
+            frequencies[outputWordIndex] = finalScore;
+            // Populate the outputChars array with the suggested word.
+            const int startIndex = outputWordIndex * MAX_WORD_LENGTH;
+            terminalDicNode->outputResult(&outputCodePoints[startIndex]);
+            ++outputWordIndex;
+        }
+
+        const bool sameAsTyped = TRAVERSAL->sameAsTyped(traverseSession, terminalDicNode);
+        outputWordIndex = ShortcutUtils::outputShortcuts(&terminalAttributes, outputWordIndex,
+                finalScore, outputCodePoints, frequencies, outputTypes, sameAsTyped);
+        DicNode::managedDelete(terminalDicNode);
+    }
+
+    if (hasMostProbableString) {
+        SCORING->safetyNetForMostProbableString(terminalSize, maxScore,
+                &outputCodePoints[0], &frequencies[0]);
+    }
+    return outputWordIndex;
+}
+
+/**
+ * Expands the dicNodes in the current search priority queue by advancing to the possible child
+ * nodes based on the next touch point(s) (or no touch points for lookahead)
+ */
+void Suggest::expandCurrentDicNodes(DicTraverseSession *traverseSession) const {
+    const int inputSize = traverseSession->getInputSize();
+    DicNodeVector childDicNodes(TRAVERSAL->getDefaultExpandDicNodeSize());
+    DicNode omissionDicNode;
+
+    // TODO: Find more efficient caching
+    const bool shouldDepthLevelCache = TRAVERSAL->shouldDepthLevelCache(traverseSession);
+    if (shouldDepthLevelCache) {
+        traverseSession->getDicTraverseCache()->updateLastCachedInputIndex();
+    }
+    if (DEBUG_CACHE) {
+        AKLOGI("expandCurrentDicNodes depth level cache = %d, inputSize = %d",
+                shouldDepthLevelCache, inputSize);
+    }
+    while (traverseSession->getDicTraverseCache()->activeSize() > 0) {
+        DicNode dicNode;
+        traverseSession->getDicTraverseCache()->popActive(&dicNode);
+        if (dicNode.isTotalInputSizeExceedingLimit()) {
+            return;
+        }
+        childDicNodes.clear();
+        const int point0Index = dicNode.getInputIndex(0);
+        const bool canDoLookAheadCorrection =
+                TRAVERSAL->canDoLookAheadCorrection(traverseSession, &dicNode);
+        const bool isLookAheadCorrection = canDoLookAheadCorrection
+                && traverseSession->getDicTraverseCache()->
+                        isLookAheadCorrectionInputIndex(static_cast<int>(point0Index));
+        const bool isCompletion = dicNode.isCompletion(inputSize);
+
+        const bool shouldNodeLevelCache =
+                TRAVERSAL->shouldNodeLevelCache(traverseSession, &dicNode);
+        if (shouldDepthLevelCache || shouldNodeLevelCache) {
+            if (DEBUG_CACHE) {
+                dicNode.dump("PUSH_CACHE");
+            }
+            traverseSession->getDicTraverseCache()->copyPushContinue(&dicNode);
+            dicNode.setCached();
+        }
+
+        if (isLookAheadCorrection) {
+            // The algorithm maintains a small set of "deferred" nodes that have not consumed the
+            // latest touch point yet. These are needed to apply look-ahead correction operations
+            // that require special handling of the latest touch point. For example, with insertions
+            // (e.g., "thiis" -> "this") the latest touch point should not be consumed at all.
+            if (CORRECT_TRANSPOSITION) {
+                processDicNodeAsTransposition(traverseSession, &dicNode);
+            }
+            if (CORRECT_INSERTION) {
+                processDicNodeAsInsertion(traverseSession, &dicNode);
+            }
+        } else { // !isLookAheadCorrection
+            // Only consider typing error corrections if the normalized compound distance is
+            // below a spatial distance threshold.
+            // NOTE: the threshold may need to be updated if scoring model changes.
+            // TODO: Remove. Do not prune node here.
+            const bool allowsErrorCorrections = TRAVERSAL->allowsErrorCorrections(&dicNode);
+            // Process for handling space substitution (e.g., hevis => he is)
+            if (allowsErrorCorrections
+                    && TRAVERSAL->isSpaceSubstitutionTerminal(traverseSession, &dicNode)) {
+                createNextWordDicNode(traverseSession, &dicNode, true /* spaceSubstitution */);
+            }
+
+            DicNodeUtils::getAllChildDicNodes(
+                    &dicNode, traverseSession->getOffsetDict(), &childDicNodes);
+
+            const int childDicNodesSize = childDicNodes.getSizeAndLock();
+            for (int i = 0; i < childDicNodesSize; ++i) {
+                DicNode *const childDicNode = childDicNodes[i];
+                if (isCompletion) {
+                    // Handle forward lookahead when the lexicon letter exceeds the input size.
+                    processDicNodeAsMatch(traverseSession, childDicNode);
+                    continue;
+                }
+                if (allowsErrorCorrections
+                        && TRAVERSAL->isOmission(traverseSession, &dicNode, childDicNode)) {
+                    // TODO: (Gesture) Change weight between omission and substitution errors
+                    // TODO: (Gesture) Terminal node should not be handled as omission
+                    omissionDicNode.initByCopy(childDicNode);
+                    processDicNodeAsOmission(traverseSession, &omissionDicNode);
+                }
+                const ProximityType proximityType = TRAVERSAL->getProximityType(
+                        traverseSession, &dicNode, childDicNode);
+                switch (proximityType) {
+                    // TODO: Consider the difference of proximityType here
+                    case MATCH_CHAR:
+                    case PROXIMITY_CHAR:
+                        processDicNodeAsMatch(traverseSession, childDicNode);
+                        break;
+                    case ADDITIONAL_PROXIMITY_CHAR:
+                        if (allowsErrorCorrections) {
+                            processDicNodeAsAdditionalProximityChar(traverseSession, &dicNode,
+                                    childDicNode);
+                        }
+                        break;
+                    case SUBSTITUTION_CHAR:
+                        if (allowsErrorCorrections) {
+                            processDicNodeAsSubstitution(traverseSession, &dicNode, childDicNode);
+                        }
+                        break;
+                    case UNRELATED_CHAR:
+                        // Just drop this node and do nothing.
+                        break;
+                    default:
+                        // Just drop this node and do nothing.
+                        break;
+                }
+            }
+
+            // Push the node for look-ahead correction
+            if (allowsErrorCorrections && canDoLookAheadCorrection) {
+                traverseSession->getDicTraverseCache()->copyPushNextActive(&dicNode);
+            }
+        }
+    }
+}
+
+void Suggest::processTerminalDicNode(
+        DicTraverseSession *traverseSession, DicNode *dicNode) const {
+    if (dicNode->getCompoundDistance() >= static_cast<float>(MAX_VALUE_FOR_WEIGHTING)) {
+        return;
+    }
+    if (!dicNode->isTerminalWordNode()) {
+        return;
+    }
+    if (TRAVERSAL->needsToTraverseAllUserInput()
+            && dicNode->getInputIndex(0) < traverseSession->getInputSize()) {
+        return;
+    }
+
+    if (dicNode->shouldBeFilterdBySafetyNetForBigram()) {
+        return;
+    }
+    // Create a non-cached node here.
+    DicNode terminalDicNode;
+    DicNodeUtils::initByCopy(dicNode, &terminalDicNode);
+    Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_TERMINAL, traverseSession, 0,
+            &terminalDicNode, traverseSession->getBigramCacheMap());
+    traverseSession->getDicTraverseCache()->copyPushTerminal(&terminalDicNode);
+}
+
+/**
+ * Adds the expanded dicNode to the next search priority queue. Also creates an additional next word
+ * (by the space omission error correction) search path if input dicNode is on a terminal node.
+ */
+void Suggest::processExpandedDicNode(
+        DicTraverseSession *traverseSession, DicNode *dicNode) const {
+    processTerminalDicNode(traverseSession, dicNode);
+    if (dicNode->getCompoundDistance() < static_cast<float>(MAX_VALUE_FOR_WEIGHTING)) {
+        if (TRAVERSAL->isSpaceOmissionTerminal(traverseSession, dicNode)) {
+            createNextWordDicNode(traverseSession, dicNode, false /* spaceSubstitution */);
+        }
+        const int allowsLookAhead = !(dicNode->hasMultipleWords()
+                && dicNode->isCompletion(traverseSession->getInputSize()));
+        if (dicNode->hasChildren() && allowsLookAhead) {
+            traverseSession->getDicTraverseCache()->copyPushNextActive(dicNode);
+        }
+    }
+    DicNode::managedDelete(dicNode);
+}
+
+void Suggest::processDicNodeAsMatch(DicTraverseSession *traverseSession,
+        DicNode *childDicNode) const {
+    weightChildNode(traverseSession, childDicNode);
+    processExpandedDicNode(traverseSession, childDicNode);
+}
+
+void Suggest::processDicNodeAsAdditionalProximityChar(DicTraverseSession *traverseSession,
+        DicNode *dicNode, DicNode *childDicNode) const {
+    Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_ADDITIONAL_PROXIMITY,
+            traverseSession, dicNode, childDicNode, 0 /* bigramCacheMap */);
+    weightChildNode(traverseSession, childDicNode);
+    processExpandedDicNode(traverseSession, childDicNode);
+}
+
+void Suggest::processDicNodeAsSubstitution(DicTraverseSession *traverseSession,
+        DicNode *dicNode, DicNode *childDicNode) const {
+    Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_SUBSTITUTION, traverseSession,
+            dicNode, childDicNode, 0 /* bigramCacheMap */);
+    weightChildNode(traverseSession, childDicNode);
+    processExpandedDicNode(traverseSession, childDicNode);
+}
+
+/**
+ * Handle the dicNode as an omission error (e.g., ths => this). Skip the current letter and consider
+ * matches for all possible next letters. Note that just skipping the current letter without any
+ * other conditions tends to flood the search dic nodes cache with omission nodes. Instead, check
+ * the possible *next* letters after the omission to better limit search to plausible omissions.
+ * Note that apostrophes are handled as omissions.
+ */
+void Suggest::processDicNodeAsOmission(
+        DicTraverseSession *traverseSession, DicNode *dicNode) const {
+    // If the omission is surely intentional that it should incur zero cost.
+    const bool isZeroCostOmission = dicNode->isZeroCostOmission();
+    DicNodeVector childDicNodes;
+
+    DicNodeUtils::getAllChildDicNodes(dicNode, traverseSession->getOffsetDict(), &childDicNodes);
+
+    const int size = childDicNodes.getSizeAndLock();
+    for (int i = 0; i < size; i++) {
+        DicNode *const childDicNode = childDicNodes[i];
+        if (!isZeroCostOmission) {
+            // Treat this word as omission
+            Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_OMISSION, traverseSession,
+                    dicNode, childDicNode, 0 /* bigramCacheMap */);
+        }
+        weightChildNode(traverseSession, childDicNode);
+
+        if (!TRAVERSAL->isPossibleOmissionChildNode(traverseSession, dicNode, childDicNode)) {
+            continue;
+        }
+        processExpandedDicNode(traverseSession, childDicNode);
+    }
+}
+
+/**
+ * Handle the dicNode as an insertion error (e.g., thiis => this). Skip the current touch point and
+ * consider matches for the next touch point.
+ */
+void Suggest::processDicNodeAsInsertion(DicTraverseSession *traverseSession,
+        DicNode *dicNode) const {
+    const int16_t pointIndex = dicNode->getInputIndex(0);
+    DicNodeVector childDicNodes;
+    DicNodeUtils::getProximityChildDicNodes(dicNode, traverseSession->getOffsetDict(),
+            traverseSession->getProximityInfoState(0), pointIndex + 1, true, &childDicNodes);
+    const int size = childDicNodes.getSizeAndLock();
+    for (int i = 0; i < size; i++) {
+        DicNode *const childDicNode = childDicNodes[i];
+        Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_INSERTION, traverseSession,
+                dicNode, childDicNode, 0 /* bigramCacheMap */);
+        processExpandedDicNode(traverseSession, childDicNode);
+    }
+}
+
+/**
+ * Handle the dicNode as a transposition error (e.g., thsi => this). Swap the next two touch points.
+ */
+void Suggest::processDicNodeAsTransposition(DicTraverseSession *traverseSession,
+        DicNode *dicNode) const {
+    const int16_t pointIndex = dicNode->getInputIndex(0);
+    DicNodeVector childDicNodes1;
+    DicNodeUtils::getProximityChildDicNodes(dicNode, traverseSession->getOffsetDict(),
+            traverseSession->getProximityInfoState(0), pointIndex + 1, false, &childDicNodes1);
+    const int childSize1 = childDicNodes1.getSizeAndLock();
+    for (int i = 0; i < childSize1; i++) {
+        if (childDicNodes1[i]->hasChildren()) {
+            DicNodeVector childDicNodes2;
+            DicNodeUtils::getProximityChildDicNodes(
+                    childDicNodes1[i], traverseSession->getOffsetDict(),
+                    traverseSession->getProximityInfoState(0), pointIndex, false, &childDicNodes2);
+            const int childSize2 = childDicNodes2.getSizeAndLock();
+            for (int j = 0; j < childSize2; j++) {
+                DicNode *const childDicNode2 = childDicNodes2[j];
+                Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_TRANSPOSITION,
+                        traverseSession, childDicNodes1[i], childDicNode2, 0 /* bigramCacheMap */);
+                processExpandedDicNode(traverseSession, childDicNode2);
+            }
+        }
+        DicNode::managedDelete(childDicNodes1[i]);
+    }
+}
+
+/**
+ * Weight child node by aligning it to the key
+ */
+void Suggest::weightChildNode(DicTraverseSession *traverseSession, DicNode *dicNode) const {
+    const int inputSize = traverseSession->getInputSize();
+    if (dicNode->isCompletion(inputSize)) {
+        Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_COMPLETION, traverseSession,
+                0 /* parentDicNode */, dicNode, 0 /* bigramCacheMap */);
+    } else { // completion
+        Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_MATCH, traverseSession,
+                0 /* parentDicNode */, dicNode, 0 /* bigramCacheMap */);
+    }
+}
+
+/**
+ * Creates a new dicNode that represents a space insertion at the end of the input dicNode. Also
+ * incorporates the unigram / bigram score for the ending word into the new dicNode.
+ */
+void Suggest::createNextWordDicNode(DicTraverseSession *traverseSession, DicNode *dicNode,
+        const bool spaceSubstitution) const {
+    if (!TRAVERSAL->isGoodToTraverseNextWord(dicNode)) {
+        return;
+    }
+
+    // Create a non-cached node here.
+    DicNode newDicNode;
+    DicNodeUtils::initAsRootWithPreviousWord(traverseSession->getDicRootPos(),
+            traverseSession->getOffsetDict(), dicNode, &newDicNode);
+    Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_NEW_WORD, traverseSession, dicNode,
+            &newDicNode, traverseSession->getBigramCacheMap());
+    if (spaceSubstitution) {
+        // Merge this with CT_NEW_WORD
+        Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_SPACE_SUBSTITUTION,
+                traverseSession, 0, &newDicNode, 0 /* bigramCacheMap */);
+    }
+    traverseSession->getDicTraverseCache()->copyPushNextActive(&newDicNode);
+}
+} // namespace latinime
diff --git a/native/jni/src/suggest/core/suggest.h b/native/jni/src/suggest/core/suggest.h
new file mode 100644
index 0000000..6c09b94
--- /dev/null
+++ b/native/jni/src/suggest/core/suggest.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_SUGGEST_IMPL_H
+#define LATINIME_SUGGEST_IMPL_H
+
+#include "defines.h"
+#include "suggest/core/suggest_interface.h"
+#include "suggest/core/policy/suggest_policy.h"
+
+namespace latinime {
+
+// Naming convention
+// - Distance: "Weighted" edit distance -- used both for spatial and language.
+// - Compound Distance: Spatial Distance + Language Distance -- used for pruning and scoring
+// - Cost: delta/diff for Distance -- used both for spatial and language
+// - Length: "Non-weighted" -- used only for spatial
+// - Probability: "Non-weighted" -- used only for language
+// - Score: Final calibrated score based on the compound distance, which is sent to java as the
+//       priority of a suggested word
+
+class DicNode;
+class DicTraverseSession;
+class ProximityInfo;
+class Scoring;
+class Traversal;
+class Weighting;
+
+class Suggest : public SuggestInterface {
+ public:
+    AK_FORCE_INLINE Suggest(const SuggestPolicy *const suggestPolicy)
+            : TRAVERSAL(suggestPolicy->getTraversal()),
+              SCORING(suggestPolicy->getScoring()), WEIGHTING(suggestPolicy->getWeighting()) {}
+    AK_FORCE_INLINE virtual ~Suggest() {}
+    int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
+            int *times, int *pointerIds, int *inputCodePoints, int inputSize, int commitPoint,
+            int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const;
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Suggest);
+    void createNextWordDicNode(DicTraverseSession *traverseSession, DicNode *dicNode,
+            const bool spaceSubstitution) const;
+    int outputSuggestions(DicTraverseSession *traverseSession, int *frequencies,
+            int *outputCodePoints, int *outputIndices, int *outputTypes) const;
+    void initializeSearch(DicTraverseSession *traverseSession, int commitPoint) const;
+    void expandCurrentDicNodes(DicTraverseSession *traverseSession) const;
+    void processTerminalDicNode(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+    void processExpandedDicNode(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+    void weightChildNode(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+    float getAutocorrectScore(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+    void generateFeatures(
+            DicTraverseSession *traverseSession, DicNode *dicNode, float *features) const;
+    void processDicNodeAsOmission(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+    void processDicNodeAsTransposition(DicTraverseSession *traverseSession,
+            DicNode *dicNode) const;
+    void processDicNodeAsInsertion(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+    void processDicNodeAsAdditionalProximityChar(DicTraverseSession *traverseSession,
+            DicNode *dicNode, DicNode *childDicNode) const;
+    void processDicNodeAsSubstitution(DicTraverseSession *traverseSession, DicNode *dicNode,
+            DicNode *childDicNode) const;
+    void processDicNodeAsMatch(DicTraverseSession *traverseSession,
+            DicNode *childDicNode) const;
+
+    // Dic nodes cache size for lookahead (autocompletion)
+    static const int LOOKAHEAD_DIC_NODES_CACHE_SIZE;
+    // Max characters to lookahead
+    static const int MAX_LOOKAHEAD;
+    // Inputs longer than this will autocorrect if the suggestion is multi-word
+    static const int MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT;
+    static const int MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE;
+    // Base value for converting costs into scores (low so will not autocorrect without classifier)
+    static const float BASE_OUTPUT_SCORE;
+
+    // Threshold for autocorrection classifier
+    static const float AUTOCORRECT_CLASSIFICATION_THRESHOLD;
+    // Threshold for computing the language model feature for autocorrect classification
+    static const float AUTOCORRECT_LANGUAGE_FEATURE_THRESHOLD;
+
+    // Typing error correction settings
+    static const bool CORRECT_SPACE_OMISSION;
+    static const bool CORRECT_TRANSPOSITION;
+    static const bool CORRECT_INSERTION;
+
+    const Traversal *const TRAVERSAL;
+    const Scoring *const SCORING;
+    const Weighting *const WEIGHTING;
+
+    static const bool CORRECT_OMISSION_G;
+};
+} // namespace latinime
+#endif // LATINIME_SUGGEST_IMPL_H
diff --git a/native/jni/src/suggest/suggest_interface.h b/native/jni/src/suggest/core/suggest_interface.h
similarity index 100%
rename from native/jni/src/suggest/suggest_interface.h
rename to native/jni/src/suggest/core/suggest_interface.h
diff --git a/native/jni/src/suggest/gesture_suggest.cpp b/native/jni/src/suggest/gesture_suggest.cpp
deleted file mode 100644
index fce5621..0000000
--- a/native/jni/src/suggest/gesture_suggest.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "gesture_suggest.h"
-
-namespace latinime {
-    SuggestInterface *(*GestureSuggest::sGestureSuggestFactoryMethod)() = 0;
-
-    GestureSuggest::~GestureSuggest() {
-        delete mSuggestInterface;
-    }
-} // namespace latinime
diff --git a/native/jni/src/suggest/gesture_suggest.h b/native/jni/src/suggest/gesture_suggest.h
deleted file mode 100644
index 82c3a69..0000000
--- a/native/jni/src/suggest/gesture_suggest.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LATINIME_GESTURE_SUGGEST_H
-#define LATINIME_GESTURE_SUGGEST_H
-
-#include "defines.h"
-#include "suggest_interface.h"
-
-namespace latinime {
-
-class ProximityInfo;
-
-class GestureSuggest : public SuggestInterface {
- public:
-    GestureSuggest() : mSuggestInterface(getGestureSuggestInstance()) {}
-
-    virtual ~GestureSuggest();
-
-    int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
-            int *times, int *pointerIds, int *inputCodePoints, int inputSize, int commitPoint,
-            int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const {
-        if (!mSuggestInterface) {
-            return 0;
-        }
-        return mSuggestInterface->getSuggestions(pInfo, traverseSession, inputXs, inputYs, times,
-                pointerIds, inputCodePoints, inputSize, commitPoint, outWords, frequencies,
-                outputIndices, outputTypes);
-    }
-
-    static void setGestureSuggestFactoryMethod(SuggestInterface *(*factoryMethod)()) {
-        sGestureSuggestFactoryMethod = factoryMethod;
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(GestureSuggest);
-    static SuggestInterface *getGestureSuggestInstance() {
-        if (!sGestureSuggestFactoryMethod) {
-            return 0;
-        }
-        return sGestureSuggestFactoryMethod();
-    }
-
-    static SuggestInterface *(*sGestureSuggestFactoryMethod)();
-    SuggestInterface *mSuggestInterface;
-};
-} // namespace latinime
-#endif // LATINIME_GESTURE_SUGGEST_H
diff --git a/native/jni/src/suggest/typing_suggest.cpp b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp
similarity index 77%
rename from native/jni/src/suggest/typing_suggest.cpp
rename to native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp
index 56bd5b6..6d31739 100644
--- a/native/jni/src/suggest/typing_suggest.cpp
+++ b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include "typing_suggest.h"
+#include "gesture_suggest_policy_factory.h"
 
 namespace latinime {
-    SuggestInterface *(*TypingSuggest::sTypingSuggestFactoryMethod)() = 0;
-
-    TypingSuggest::~TypingSuggest() {
-        delete mSuggestInterface;
-    }
+    const SuggestPolicy *(*GestureSuggestPolicyFactory::sGestureSuggestFactoryMethod)() = 0;
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.h b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.h
new file mode 100644
index 0000000..509b01f
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_GESTURE_SUGGEST_POLICY_FACTORY_H
+#define LATINIME_GESTURE_SUGGEST_POLICY_FACTORY_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class SuggestPolicy;
+
+class GestureSuggestPolicyFactory {
+ public:
+    static void setGestureSuggestPolicyFactoryMethod(const SuggestPolicy *(*factoryMethod)()) {
+        sGestureSuggestFactoryMethod = factoryMethod;
+    }
+
+    static const SuggestPolicy *getGestureSuggestPolicy() {
+        if (!sGestureSuggestFactoryMethod) {
+            return 0;
+        }
+        return sGestureSuggestFactoryMethod();
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(GestureSuggestPolicyFactory);
+    static const SuggestPolicy *(*sGestureSuggestFactoryMethod)();
+};
+} // namespace latinime
+#endif // LATINIME_GESTURE_SUGGEST_POLICY_FACTORY_H
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
new file mode 100644
index 0000000..0fa684f
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+// TODO: RENAME all
+const float ScoringParams::MAX_SPATIAL_DISTANCE = 1.0f;
+const int ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY = 40;
+const int ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED = 120;
+const float ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD = 1.0f;
+const int ScoringParams::MAX_CACHE_DIC_NODE_SIZE = 125;
+const int ScoringParams::THRESHOLD_SHORT_WORD_LENGTH = 4;
+
+const float ScoringParams::DISTANCE_WEIGHT_LENGTH = 0.132f;
+const float ScoringParams::PROXIMITY_COST = 0.086f;
+const float ScoringParams::FIRST_PROXIMITY_COST = 0.104f;
+const float ScoringParams::OMISSION_COST = 0.388f;
+const float ScoringParams::OMISSION_COST_SAME_CHAR = 0.431f;
+const float ScoringParams::OMISSION_COST_FIRST_CHAR = 0.532f;
+const float ScoringParams::INSERTION_COST = 0.670f;
+const float ScoringParams::INSERTION_COST_SAME_CHAR = 0.526f;
+const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.563f;
+const float ScoringParams::TRANSPOSITION_COST = 0.494f;
+const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.239f;
+const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.380f;
+const float ScoringParams::SUBSTITUTION_COST = 0.363f;
+const float ScoringParams::COST_NEW_WORD = 0.054f;
+const float ScoringParams::COST_NEW_WORD_CAPITALIZED = 0.174f;
+const float ScoringParams::DISTANCE_WEIGHT_LANGUAGE = 1.123f;
+const float ScoringParams::COST_FIRST_LOOKAHEAD = 0.462f;
+const float ScoringParams::COST_LOOKAHEAD = 0.092f;
+const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.126f;
+const float ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST = 0.056f;
+const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.136f;
+const float ScoringParams::TYPING_BASE_OUTPUT_SCORE = 1.0f;
+const float ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT = 0.1f;
+const float ScoringParams::MAX_NORM_DISTANCE_FOR_EDIT = 0.1f;
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.h b/native/jni/src/suggest/policyimpl/typing/scoring_params.h
new file mode 100644
index 0000000..8f104b3
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_SCORING_PARAMS_H
+#define LATINIME_SCORING_PARAMS_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class ScoringParams {
+ public:
+    // Fixed model parameters
+    static const float MAX_SPATIAL_DISTANCE;
+    static const int THRESHOLD_NEXT_WORD_PROBABILITY;
+    static const int THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
+    static const float AUTOCORRECT_OUTPUT_THRESHOLD;
+    static const int MAX_CACHE_DIC_NODE_SIZE;
+    static const int THRESHOLD_SHORT_WORD_LENGTH;
+
+    // Numerically optimized parameters (currently for tap typing only).
+    // TODO: add ability to modify these constants programmatically.
+    // TODO: explore optimization of gesture parameters.
+    static const float DISTANCE_WEIGHT_LENGTH;
+    static const float PROXIMITY_COST;
+    static const float FIRST_PROXIMITY_COST;
+    static const float OMISSION_COST;
+    static const float OMISSION_COST_SAME_CHAR;
+    static const float OMISSION_COST_FIRST_CHAR;
+    static const float INSERTION_COST;
+    static const float INSERTION_COST_SAME_CHAR;
+    static const float INSERTION_COST_FIRST_CHAR;
+    static const float TRANSPOSITION_COST;
+    static const float SPACE_SUBSTITUTION_COST;
+    static const float ADDITIONAL_PROXIMITY_COST;
+    static const float SUBSTITUTION_COST;
+    static const float COST_NEW_WORD;
+    static const float COST_NEW_WORD_CAPITALIZED;
+    static const float DISTANCE_WEIGHT_LANGUAGE;
+    static const float COST_FIRST_LOOKAHEAD;
+    static const float COST_LOOKAHEAD;
+    static const float HAS_PROXIMITY_TERMINAL_COST;
+    static const float HAS_EDIT_CORRECTION_TERMINAL_COST;
+    static const float HAS_MULTI_WORD_TERMINAL_COST;
+    static const float TYPING_BASE_OUTPUT_SCORE;
+    static const float TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
+    static const float MAX_NORM_DISTANCE_FOR_EDIT;
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ScoringParams);
+};
+} // namespace latinime
+#endif // LATINIME_SCORING_PARAMS_H
diff --git a/native/jni/src/suggest/typing_suggest.cpp b/native/jni/src/suggest/policyimpl/typing/typing_scoring.cpp
similarity index 68%
copy from native/jni/src/suggest/typing_suggest.cpp
copy to native/jni/src/suggest/policyimpl/typing/typing_scoring.cpp
index 56bd5b6..d8c6175 100644
--- a/native/jni/src/suggest/typing_suggest.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include "typing_suggest.h"
+#include "suggest/policyimpl/typing/typing_scoring.h"
 
 namespace latinime {
-    SuggestInterface *(*TypingSuggest::sTypingSuggestFactoryMethod)() = 0;
-
-    TypingSuggest::~TypingSuggest() {
-        delete mSuggestInterface;
-    }
-} // namespace latinime
+const TypingScoring TypingScoring::sInstance;
+}  // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
new file mode 100644
index 0000000..90e2133
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_TYPING_SCORING_H
+#define LATINIME_TYPING_SCORING_H
+
+#include "defines.h"
+#include "suggest/core/policy/scoring.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+
+class DicNode;
+class DicTraverseSession;
+
+class TypingScoring : public Scoring {
+ public:
+    static const TypingScoring *getInstance() { return &sInstance; }
+
+    AK_FORCE_INLINE bool getMostProbableString(
+            const DicTraverseSession *const traverseSession, const int terminalSize,
+            const float languageWeight, int *const outputCodePoints, int *const type,
+            int *const freq) const {
+        return false;
+    }
+
+    AK_FORCE_INLINE void safetyNetForMostProbableString(const int terminalSize,
+            const int maxScore, int *const outputCodePoints, int *const frequencies) const {
+    }
+
+    AK_FORCE_INLINE void searchWordWithDoubleLetter(DicNode *terminals,
+            const int terminalSize, int *doubleLetterTerminalIndex,
+            DoubleLetterLevel *doubleLetterLevel) const {
+    }
+
+    AK_FORCE_INLINE float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
+             DicNode *const terminals, const int size) const {
+        return 1.0f;
+    }
+
+    AK_FORCE_INLINE int calculateFinalScore(const float compoundDistance,
+            const int inputSize, const bool forceCommit) const {
+        const float maxDistance = ScoringParams::DISTANCE_WEIGHT_LANGUAGE
+                + static_cast<float>(inputSize) * ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
+        return static_cast<int>((ScoringParams::TYPING_BASE_OUTPUT_SCORE
+                - (compoundDistance / maxDistance)
+                + (forceCommit ? ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD : 0.0f))
+                        * SUGGEST_INTERFACE_OUTPUT_SCALE);
+    }
+
+    AK_FORCE_INLINE float getDoubleLetterDemotionDistanceCost(const int terminalIndex,
+            const int doubleLetterTerminalIndex,
+            const DoubleLetterLevel doubleLetterLevel) const {
+        return 0.0f;
+    }
+
+    AK_FORCE_INLINE bool doesAutoCorrectValidWord() const {
+        return false;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TypingScoring);
+    static const TypingScoring sInstance;
+
+    TypingScoring() {}
+    ~TypingScoring() {}
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_SCORING_H
diff --git a/native/jni/src/suggest/typing_suggest.cpp b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.cpp
similarity index 71%
copy from native/jni/src/suggest/typing_suggest.cpp
copy to native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.cpp
index 56bd5b6..0c27639 100644
--- a/native/jni/src/suggest/typing_suggest.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include "typing_suggest.h"
+#include "suggest/policyimpl/typing/typing_suggest_policy.h"
 
 namespace latinime {
-    SuggestInterface *(*TypingSuggest::sTypingSuggestFactoryMethod)() = 0;
-
-    TypingSuggest::~TypingSuggest() {
-        delete mSuggestInterface;
-    }
+const TypingSuggestPolicy TypingSuggestPolicy::sInstance;
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.h b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.h
new file mode 100644
index 0000000..35f4809
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_TYPING_SUGGEST_POLICY_H
+#define LATINIME_TYPING_SUGGEST_POLICY_H
+
+#include "defines.h"
+#include "suggest/core/policy/suggest_policy.h"
+#include "suggest/policyimpl/typing/typing_scoring.h"
+#include "suggest/policyimpl/typing/typing_traversal.h"
+#include "suggest/policyimpl/typing/typing_weighting.h"
+
+namespace latinime {
+
+class Scoring;
+class Traversal;
+class Weighting;
+
+class TypingSuggestPolicy : public SuggestPolicy {
+ public:
+    static const TypingSuggestPolicy *getInstance() { return &sInstance; }
+
+    TypingSuggestPolicy() {}
+    virtual ~TypingSuggestPolicy() {}
+    AK_FORCE_INLINE const Traversal *getTraversal() const {
+        return TypingTraversal::getInstance();
+    }
+
+    AK_FORCE_INLINE const Scoring *getScoring() const {
+        return TypingScoring::getInstance();
+    }
+
+    AK_FORCE_INLINE const Weighting *getWeighting() const {
+        return TypingWeighting::getInstance();
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TypingSuggestPolicy);
+    static const TypingSuggestPolicy sInstance;
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_SUGGEST_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy_factory.h b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy_factory.h
new file mode 100644
index 0000000..a67b45b
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy_factory.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_TYPING_SUGGEST_POLICY_FACTORY_H
+#define LATINIME_TYPING_SUGGEST_POLICY_FACTORY_H
+
+#include "defines.h"
+#include "typing_suggest_policy.h"
+
+namespace latinime {
+
+class SuggestPolicy;
+
+class TypingSuggestPolicyFactory {
+ public:
+    static const SuggestPolicy *getTypingSuggestPolicy() {
+        return TypingSuggestPolicy::getInstance();
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TypingSuggestPolicyFactory);
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_SUGGEST_POLICY_FACTORY_H
diff --git a/native/jni/src/suggest/typing_suggest.cpp b/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
similarity index 61%
copy from native/jni/src/suggest/typing_suggest.cpp
copy to native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
index 56bd5b6..66f8ba9 100644
--- a/native/jni/src/suggest/typing_suggest.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-#include "typing_suggest.h"
+#include "suggest/policyimpl/typing/typing_traversal.h"
 
 namespace latinime {
-    SuggestInterface *(*TypingSuggest::sTypingSuggestFactoryMethod)() = 0;
-
-    TypingSuggest::~TypingSuggest() {
-        delete mSuggestInterface;
-    }
-} // namespace latinime
+const bool TypingTraversal::CORRECT_OMISSION = true;
+const bool TypingTraversal::CORRECT_SPACE_SUBSTITUTION = true;
+const bool TypingTraversal::CORRECT_SPACE_OMISSION = true;
+const TypingTraversal TypingTraversal::sInstance;
+}  // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
new file mode 100644
index 0000000..f22029a
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_TYPING_TRAVERSAL_H
+#define LATINIME_TYPING_TRAVERSAL_H
+
+#include <stdint.h>
+
+#include "char_utils.h"
+#include "defines.h"
+#include "proximity_info_state.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/policy/traversal.h"
+#include "suggest/core/session/dic_traverse_session.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+class TypingTraversal : public Traversal {
+ public:
+    static const TypingTraversal *getInstance() { return &sInstance; }
+
+    AK_FORCE_INLINE int getMaxPointerCount() const {
+        return MAX_POINTER_COUNT;
+    }
+
+    AK_FORCE_INLINE bool allowsErrorCorrections(const DicNode *const dicNode) const {
+        return dicNode->getNormalizedSpatialDistance()
+                < ScoringParams::MAX_NORM_DISTANCE_FOR_EDIT;
+    }
+
+    AK_FORCE_INLINE bool isOmission(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode, const DicNode *const childDicNode) const {
+        if (!CORRECT_OMISSION) {
+            return false;
+        }
+        const int inputSize = traverseSession->getInputSize();
+        // TODO: Don't refer to isCompletion?
+        if (dicNode->isCompletion(inputSize)) {
+            return false;
+        }
+        if (dicNode->canBeIntentionalOmission()) {
+            return true;
+        }
+        const int point0Index = dicNode->getInputIndex(0);
+        const int currentBaseLowerCodePoint =
+                toBaseLowerCase(childDicNode->getNodeCodePoint());
+        const int typedBaseLowerCodePoint =
+                toBaseLowerCase(traverseSession->getProximityInfoState(0)
+                        ->getPrimaryCodePointAt(point0Index));
+        return (currentBaseLowerCodePoint != typedBaseLowerCodePoint);
+    }
+
+    AK_FORCE_INLINE bool isSpaceSubstitutionTerminal(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+        if (!CORRECT_SPACE_SUBSTITUTION) {
+            return false;
+        }
+        if (!canDoLookAheadCorrection(traverseSession, dicNode)) {
+            return false;
+        }
+        const int point0Index = dicNode->getInputIndex(0);
+        return dicNode->isTerminalWordNode()
+                && traverseSession->getProximityInfoState(0)->
+                        hasSpaceProximity(point0Index);
+    }
+
+    AK_FORCE_INLINE bool isSpaceOmissionTerminal(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+        if (!CORRECT_SPACE_OMISSION) {
+            return false;
+        }
+        const int inputSize = traverseSession->getInputSize();
+        // TODO: Don't refer to isCompletion?
+        if (dicNode->isCompletion(inputSize)) {
+            return false;
+        }
+        if (!dicNode->isTerminalWordNode()) {
+            return false;
+        }
+        const int16_t pointIndex = dicNode->getInputIndex(0);
+        return pointIndex <= inputSize && !dicNode->isTotalInputSizeExceedingLimit()
+                && !dicNode->shouldBeFilterdBySafetyNetForBigram();
+    }
+
+    AK_FORCE_INLINE bool shouldDepthLevelCache(
+            const DicTraverseSession *const traverseSession) const {
+        const int inputSize = traverseSession->getInputSize();
+        return traverseSession->isCacheBorderForTyping(inputSize);
+    }
+
+    AK_FORCE_INLINE bool shouldNodeLevelCache(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+        return false;
+    }
+
+    AK_FORCE_INLINE bool canDoLookAheadCorrection(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+        const int inputSize = traverseSession->getInputSize();
+        return dicNode->canDoLookAheadCorrection(inputSize);
+    }
+
+    AK_FORCE_INLINE ProximityType getProximityType(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+            const DicNode *const childDicNode) const {
+        return traverseSession->getProximityInfoState(0)->getProximityType(
+                dicNode->getInputIndex(0), childDicNode->getNodeCodePoint(),
+                true /* checkProximityChars */);
+    }
+
+    AK_FORCE_INLINE bool needsToTraverseAllUserInput() const {
+        return true;
+    }
+
+    AK_FORCE_INLINE float getMaxSpatialDistance() const {
+        return ScoringParams::MAX_SPATIAL_DISTANCE;
+    }
+
+    AK_FORCE_INLINE bool allowPartialCommit() const {
+        return true;
+    }
+
+    AK_FORCE_INLINE int getDefaultExpandDicNodeSize() const {
+        return DicNodeVector::DEFAULT_NODES_SIZE_FOR_OPTIMIZATION;
+    }
+
+    AK_FORCE_INLINE bool sameAsTyped(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+        return traverseSession->getProximityInfoState(0)->sameAsTyped(
+                dicNode->getOutputWordBuf(), dicNode->getDepth());
+    }
+
+    AK_FORCE_INLINE int getMaxCacheSize() const {
+        return ScoringParams::MAX_CACHE_DIC_NODE_SIZE;
+    }
+
+    AK_FORCE_INLINE bool isPossibleOmissionChildNode(
+            const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
+            const DicNode *const dicNode) const {
+        const ProximityType proximityType =
+                getProximityType(traverseSession, parentDicNode, dicNode);
+        if (!DicNodeUtils::isProximityChar(proximityType)) {
+            return false;
+        }
+        return true;
+    }
+
+    AK_FORCE_INLINE bool isGoodToTraverseNextWord(const DicNode *const dicNode) const {
+        const int probability = dicNode->getProbability();
+        if (probability < ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY) {
+            return false;
+        }
+        const int c = dicNode->getOutputWordBuf()[0];
+        const bool shortCappedWord = dicNode->getDepth()
+                < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && isAsciiUpper(c);
+        return !shortCappedWord
+                || probability >= ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TypingTraversal);
+    static const bool CORRECT_OMISSION;
+    static const bool CORRECT_SPACE_SUBSTITUTION;
+    static const bool CORRECT_SPACE_OMISSION;
+    static const TypingTraversal sInstance;
+
+    TypingTraversal() {}
+    ~TypingTraversal() {}
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_TRAVERSAL_H
diff --git a/native/jni/src/suggest/typing_suggest.cpp b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
similarity index 73%
copy from native/jni/src/suggest/typing_suggest.cpp
copy to native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
index 56bd5b6..1500341 100644
--- a/native/jni/src/suggest/typing_suggest.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-#include "typing_suggest.h"
+#include "suggest/policyimpl/typing/typing_weighting.h"
+
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
 
 namespace latinime {
-    SuggestInterface *(*TypingSuggest::sTypingSuggestFactoryMethod)() = 0;
-
-    TypingSuggest::~TypingSuggest() {
-        delete mSuggestInterface;
-    }
-} // namespace latinime
+const TypingWeighting TypingWeighting::sInstance;
+}  // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
new file mode 100644
index 0000000..52d54eb
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_TYPING_WEIGHTING_H
+#define LATINIME_TYPING_WEIGHTING_H
+
+#include "defines.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/policy/weighting.h"
+#include "suggest/core/session/dic_traverse_session.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+
+class DicNode;
+struct DicNode_InputStateG;
+
+class TypingWeighting : public Weighting {
+ public:
+    static const TypingWeighting *getInstance() { return &sInstance; }
+
+ protected:
+    float getTerminalSpatialCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+        float cost = 0.0f;
+        if (dicNode->hasMultipleWords()) {
+            cost += ScoringParams::HAS_MULTI_WORD_TERMINAL_COST;
+        }
+        if (dicNode->getProximityCorrectionCount() > 0) {
+            cost += ScoringParams::HAS_PROXIMITY_TERMINAL_COST;
+        }
+        if (dicNode->getEditCorrectionCount() > 0) {
+            cost += ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST;
+        }
+        return cost;
+    }
+
+    float getOmissionCost(const DicNode *const parentDicNode, const DicNode *const dicNode) const {
+        bool sameCodePoint = false;
+        bool isFirstLetterOmission = false;
+        float cost = 0.0f;
+        sameCodePoint = dicNode->isSameNodeCodePoint(parentDicNode);
+        // If the traversal omitted the first letter then the dicNode should now be on the second.
+        isFirstLetterOmission = dicNode->getDepth() == 2;
+        if (isFirstLetterOmission) {
+            cost = ScoringParams::OMISSION_COST_FIRST_CHAR;
+        } else {
+            cost = sameCodePoint ? ScoringParams::OMISSION_COST_SAME_CHAR
+                    : ScoringParams::OMISSION_COST;
+        }
+        return cost;
+    }
+
+    float getMatchedCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+            DicNode_InputStateG *inputStateG) const {
+        const int pointIndex = dicNode->getInputIndex(0);
+        // Note: min() required since length can be MAX_POINT_TO_KEY_LENGTH for characters not on
+        // the keyboard (like accented letters)
+        const float length = min(ScoringParams::MAX_SPATIAL_DISTANCE,
+                traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+                        pointIndex, dicNode->getNodeCodePoint()));
+        const float weightedDistance = length * ScoringParams::DISTANCE_WEIGHT_LENGTH;
+        const bool isFirstChar = pointIndex == 0;
+        const bool isProximity = isProximityDicNode(traverseSession, dicNode);
+        const float cost = isProximity ? (isFirstChar ? ScoringParams::FIRST_PROXIMITY_COST
+                : ScoringParams::PROXIMITY_COST) : 0.0f;
+        return weightedDistance + cost;
+    }
+
+    bool isProximityDicNode(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+        const int pointIndex = dicNode->getInputIndex(0);
+        const int primaryCodePoint = toBaseLowerCase(
+                traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(pointIndex));
+        const int dicNodeChar = toBaseLowerCase(dicNode->getNodeCodePoint());
+        return primaryCodePoint != dicNodeChar;
+    }
+
+    float getTranspositionCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
+            const DicNode *const dicNode) const {
+        const int16_t parentPointIndex = parentDicNode->getInputIndex(0);
+        const int prevCodePoint = parentDicNode->getNodeCodePoint();
+        const float distance1 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+                parentPointIndex + 1, prevCodePoint);
+        const int codePoint = dicNode->getNodeCodePoint();
+        const float distance2 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+                parentPointIndex, codePoint);
+        const float distance = distance1 + distance2;
+        const float weightedLengthDistance =
+                distance * ScoringParams::DISTANCE_WEIGHT_LENGTH;
+        return ScoringParams::TRANSPOSITION_COST + weightedLengthDistance;
+    }
+
+    float getInsertionCost(
+            const DicTraverseSession *const traverseSession,
+            const DicNode *const parentDicNode, const DicNode *const dicNode) const {
+        const int16_t parentPointIndex = parentDicNode->getInputIndex(0);
+        const int prevCodePoint =
+                traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(parentPointIndex);
+
+        const int currentCodePoint = dicNode->getNodeCodePoint();
+        const bool sameCodePoint = prevCodePoint == currentCodePoint;
+        const float dist = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+                parentPointIndex + 1, currentCodePoint);
+        const float weightedDistance = dist * ScoringParams::DISTANCE_WEIGHT_LENGTH;
+        const bool singleChar = dicNode->getDepth() == 1;
+        const float cost = (singleChar ? ScoringParams::INSERTION_COST_FIRST_CHAR : 0.0f)
+                + (sameCodePoint ? ScoringParams::INSERTION_COST_SAME_CHAR
+                        : ScoringParams::INSERTION_COST);
+        return cost + weightedDistance;
+    }
+
+    float getNewWordCost(const DicNode *const dicNode) const {
+        const bool isCapitalized = dicNode->isCapitalized();
+        return isCapitalized ?
+                ScoringParams::COST_NEW_WORD_CAPITALIZED : ScoringParams::COST_NEW_WORD;
+    }
+
+    float getNewWordBigramCost(
+            const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+            hash_map_compat<int, int16_t> *const bigramCacheMap) const {
+        return DicNodeUtils::getBigramNodeImprobability(traverseSession->getOffsetDict(),
+                dicNode, bigramCacheMap);
+    }
+
+    float getCompletionCost(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode) const {
+        // The auto completion starts when the input index is same as the input size
+        const bool firstCompletion = dicNode->getInputIndex(0)
+                == traverseSession->getInputSize();
+        // TODO: Change the cost for the first completion for the gesture?
+        const float cost = firstCompletion ? ScoringParams::COST_FIRST_LOOKAHEAD
+                : ScoringParams::COST_LOOKAHEAD;
+        return cost;
+    }
+
+    float getTerminalLanguageCost(const DicTraverseSession *const traverseSession,
+            const DicNode *const dicNode, const float dicNodeLanguageImprobability) const {
+        const bool hasEditCount = dicNode->getEditCorrectionCount() > 0;
+        const bool isSameLength = dicNode->getDepth() == traverseSession->getInputSize();
+        const bool hasMultipleWords = dicNode->hasMultipleWords();
+        const bool hasProximityErrors = dicNode->getProximityCorrectionCount() > 0;
+        // Gesture input is always assumed to have proximity errors
+        // because the input word shouldn't be treated as perfect
+        const bool isExactMatch = !hasEditCount && !hasMultipleWords
+                && !hasProximityErrors && isSameLength;
+
+        const float totalPrevWordsLanguageCost = dicNode->getTotalPrevWordsLanguageCost();
+        const float languageImprobability = isExactMatch ? 0.0f : dicNodeLanguageImprobability;
+        const float languageWeight = ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
+        // TODO: Caveat: The following equation should be:
+        // totalPrevWordsLanguageCost + (languageImprobability * languageWeight);
+        return (totalPrevWordsLanguageCost + languageImprobability) * languageWeight;
+    }
+
+    AK_FORCE_INLINE bool needsToNormalizeCompoundDistance() const {
+        return false;
+    }
+
+    AK_FORCE_INLINE float getAdditionalProximityCost() const {
+        return ScoringParams::ADDITIONAL_PROXIMITY_COST;
+    }
+
+    AK_FORCE_INLINE float getSubstitutionCost() const {
+        return ScoringParams::SUBSTITUTION_COST;
+    }
+
+    AK_FORCE_INLINE float getSpaceSubstitutionCost() const {
+        return ScoringParams::SPACE_SUBSTITUTION_COST;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TypingWeighting);
+    static const TypingWeighting sInstance;
+
+    TypingWeighting() {}
+    ~TypingWeighting() {}
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_WEIGHTING_H
diff --git a/native/jni/src/suggest/typing_suggest.h b/native/jni/src/suggest/typing_suggest.h
deleted file mode 100644
index 678037a..0000000
--- a/native/jni/src/suggest/typing_suggest.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LATINIME_TYPING_SUGGEST_H
-#define LATINIME_TYPING_SUGGEST_H
-
-#include "defines.h"
-#include "suggest_interface.h"
-
-namespace latinime {
-
-class ProximityInfo;
-
-class TypingSuggest : public SuggestInterface {
- public:
-    TypingSuggest() : mSuggestInterface(getTypingSuggestInstance()) {}
-
-    virtual ~TypingSuggest();
-
-    int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
-            int *times, int *pointerIds, int *inputCodePoints, int inputSize, int commitPoint,
-            int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const {
-        if (!mSuggestInterface) {
-            return 0;
-        }
-        return mSuggestInterface->getSuggestions(pInfo, traverseSession, inputXs, inputYs, times,
-                pointerIds, inputCodePoints, inputSize, commitPoint, outWords, frequencies,
-                outputIndices, outputTypes);
-    }
-
-    static void setTypingSuggestFactoryMethod(SuggestInterface *(*factoryMethod)()) {
-        sTypingSuggestFactoryMethod = factoryMethod;
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(TypingSuggest);
-    static SuggestInterface *getTypingSuggestInstance() {
-        if (!sTypingSuggestFactoryMethod) {
-            return 0;
-        }
-        return sTypingSuggestFactoryMethod();
-    }
-
-    static SuggestInterface *(*sTypingSuggestFactoryMethod)();
-    SuggestInterface *mSuggestInterface;
-};
-} // namespace latinime
-#endif // LATINIME_TYPING_SUGGEST_H
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index 80ba412..a672294 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -22,6 +22,7 @@
 #include "char_utils.h"
 #include "defines.h"
 #include "dictionary.h"
+#include "digraph_utils.h"
 #include "proximity_info.h"
 #include "terminal_attributes.h"
 #include "unigram_dictionary.h"
@@ -30,19 +31,10 @@
 
 namespace latinime {
 
-const UnigramDictionary::digraph_t UnigramDictionary::GERMAN_UMLAUT_DIGRAPHS[] =
-        { { 'a', 'e', 0x00E4 }, // U+00E4 : LATIN SMALL LETTER A WITH DIAERESIS
-        { 'o', 'e', 0x00F6 }, // U+00F6 : LATIN SMALL LETTER O WITH DIAERESIS
-        { 'u', 'e', 0x00FC } }; // U+00FC : LATIN SMALL LETTER U WITH DIAERESIS
-
-const UnigramDictionary::digraph_t UnigramDictionary::FRENCH_LIGATURES_DIGRAPHS[] =
-        { { 'a', 'e', 0x00E6 }, // U+00E6 : LATIN SMALL LETTER AE
-        { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE
-
 // TODO: check the header
-UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, const unsigned int flags)
+UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, const unsigned int dictFlags)
         : DICT_ROOT(streamStart), ROOT_POS(0),
-          MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), FLAGS(flags) {
+          MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), DICT_FLAGS(dictFlags) {
     if (DEBUG_DICT) {
         AKLOGI("UnigramDictionary - constructor");
     }
@@ -58,7 +50,7 @@
 
 // Return the replacement code point for a digraph, or 0 if none.
 int UnigramDictionary::getDigraphReplacement(const int *codes, const int i, const int inputSize,
-        const digraph_t *const digraphs, const unsigned int digraphsSize) const {
+        const DigraphUtils::digraph_t *const digraphs, const unsigned int digraphsSize) const {
 
     // There can't be a digraph if we don't have at least 2 characters to examine
     if (i + 2 > inputSize) return false;
@@ -74,7 +66,7 @@
 
     // It's an interesting digraph if the second char matches too.
     if (digraphs[lastDigraphIndex].second == codes[i + 1]) {
-        return digraphs[lastDigraphIndex].replacement;
+        return digraphs[lastDigraphIndex].compositeGlyph;
     } else {
         return 0;
     }
@@ -93,7 +85,7 @@
         const bool useFullEditDistance, const int *codesSrc,
         const int codesRemain, const int currentDepth, int *codesDest, Correction *correction,
         WordsPriorityQueuePool *queuePool,
-        const digraph_t *const digraphs, const unsigned int digraphsSize) const {
+        const DigraphUtils::digraph_t *const digraphs, const unsigned int digraphsSize) const {
     ASSERT(sizeof(codesDest[0]) == sizeof(codesSrc[0]));
     ASSERT(sizeof(xCoordinatesBuffer[0]) == sizeof(xcoordinates[0]));
     ASSERT(sizeof(yCoordinatesBuffer[0]) == sizeof(ycoordinates[0]));
@@ -169,7 +161,10 @@
     queuePool.clearAll();
     Correction masterCorrection;
     masterCorrection.resetCorrection();
-    if (BinaryFormat::REQUIRES_GERMAN_UMLAUT_PROCESSING & FLAGS)
+    const DigraphUtils::digraph_t *digraphs = 0;
+    const int digraphsSize =
+            DigraphUtils::getAllDigraphsForDictionaryAndReturnSize(DICT_FLAGS, &digraphs);
+    if (digraphsSize > 0)
     { // Incrementally tune the word and try all possibilities
         int codesBuffer[sizeof(*inputCodePoints) * inputSize];
         int xCoordinatesBuffer[inputSize];
@@ -177,15 +172,7 @@
         getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer,
                 xCoordinatesBuffer, yCoordinatesBuffer, inputSize, bigramMap, bigramFilter,
                 useFullEditDistance, inputCodePoints, inputSize, 0, codesBuffer, &masterCorrection,
-                &queuePool, GERMAN_UMLAUT_DIGRAPHS, NELEMS(GERMAN_UMLAUT_DIGRAPHS));
-    } else if (BinaryFormat::REQUIRES_FRENCH_LIGATURES_PROCESSING & FLAGS) {
-        int codesBuffer[sizeof(*inputCodePoints) * inputSize];
-        int xCoordinatesBuffer[inputSize];
-        int yCoordinatesBuffer[inputSize];
-        getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer,
-                xCoordinatesBuffer, yCoordinatesBuffer, inputSize, bigramMap, bigramFilter,
-                useFullEditDistance, inputCodePoints, inputSize, 0, codesBuffer, &masterCorrection,
-                &queuePool, FRENCH_LIGATURES_DIGRAPHS, NELEMS(FRENCH_LIGATURES_DIGRAPHS));
+                &queuePool, digraphs, digraphsSize);
     } else { // Normal processing
         getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, inputCodePoints, inputSize,
                 bigramMap, bigramFilter, useFullEditDistance, &masterCorrection, &queuePool);
diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h
index c1955e8..a64a539 100644
--- a/native/jni/src/unigram_dictionary.h
+++ b/native/jni/src/unigram_dictionary.h
@@ -20,6 +20,7 @@
 #include <map>
 #include <stdint.h>
 #include "defines.h"
+#include "digraph_utils.h"
 
 namespace latinime {
 
@@ -29,8 +30,6 @@
 class WordsPriorityQueuePool;
 
 class UnigramDictionary {
-    typedef struct { int first; int second; int replacement; } digraph_t;
-
  public:
     // Error tolerances
     static const int DEFAULT_MAX_ERRORS = 2;
@@ -39,7 +38,7 @@
     static const int FLAG_MULTIPLE_SUGGEST_ABORT = 0;
     static const int FLAG_MULTIPLE_SUGGEST_SKIP = 1;
     static const int FLAG_MULTIPLE_SUGGEST_CONTINUE = 2;
-    UnigramDictionary(const uint8_t *const streamStart, const unsigned int flags);
+    UnigramDictionary(const uint8_t *const streamStart, const unsigned int dictFlags);
     int getProbability(const int *const inWord, const int length) const;
     int getBigramPosition(int pos, int *word, int offset, int length) const;
     int getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
@@ -47,6 +46,7 @@
             const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
             const bool useFullEditDistance, int *outWords, int *frequencies,
             int *outputTypes) const;
+    int getDictFlags() const { return DICT_FLAGS; }
     virtual ~UnigramDictionary();
 
  private:
@@ -57,13 +57,13 @@
             const bool useFullEditDistance, Correction *correction,
             WordsPriorityQueuePool *queuePool) const;
     int getDigraphReplacement(const int *codes, const int i, const int inputSize,
-            const digraph_t *const digraphs, const unsigned int digraphsSize) const;
+            const DigraphUtils::digraph_t *const digraphs, const unsigned int digraphsSize) const;
     void getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo, const int *xcoordinates,
             const int *ycoordinates, const int *codesBuffer, int *xCoordinatesBuffer,
             int *yCoordinatesBuffer, const int codesBufferSize, const std::map<int, int> *bigramMap,
             const uint8_t *bigramFilter, const bool useFullEditDistance, const int *codesSrc,
             const int codesRemain, const int currentDepth, int *codesDest, Correction *correction,
-            WordsPriorityQueuePool *queuePool, const digraph_t *const digraphs,
+            WordsPriorityQueuePool *queuePool, const DigraphUtils::digraph_t *const digraphs,
             const unsigned int digraphsSize) const;
     void initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
             const int *ycoordinates, const int *codes, const int inputSize,
@@ -110,10 +110,7 @@
     const uint8_t *const DICT_ROOT;
     const int ROOT_POS;
     const int MAX_DIGRAPH_SEARCH_DEPTH;
-    const int FLAGS;
-
-    static const digraph_t GERMAN_UMLAUT_DIGRAPHS[];
-    static const digraph_t FRENCH_LIGATURES_DIGRAPHS[];
+    const int DICT_FLAGS;
 };
 } // namespace latinime
 #endif // LATINIME_UNIGRAM_DICTIONARY_H
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/HermiteInterpolatorTests.java b/tests/src/com/android/inputmethod/keyboard/internal/HermiteInterpolatorTests.java
new file mode 100644
index 0000000..3ff5aa4
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/internal/HermiteInterpolatorTests.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class HermiteInterpolatorTests extends AndroidTestCase {
+    private final HermiteInterpolator mInterpolator = new HermiteInterpolator();
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    private static final float EPSLION = 0.0000005f;
+
+    private static void assertFloatEquals(final String message, float expected, float actual) {
+        if (Math.abs(expected - actual) >= EPSLION) {
+            fail(String.format("%s expected:<%s> but was:<%s>", message, expected, actual));
+        }
+    }
+
+    // t=0 p0=(0,1)
+    // t=1 p1=(1,0)
+    // t=2 p2=(3,2)
+    // t=3 p3=(2,3)
+    //   y
+    //   |
+    // 3 +       o p3
+    //   |
+    // 2 +           o p2
+    //   |
+    // 1 o p0
+    //   |    p1
+    // 0 +---o---+---+-- x
+    //   0   1   2   3
+    private final int[] mXCoords = { 0, 1, 3, 2 };
+    private final int[] mYCoords = { 1, 0, 2, 3 };
+    private static final int p0 = 0;
+    private static final int p1 = 1;
+    private static final int p2 = 2;
+    private static final int p3 = 3;
+
+    public void testP0P1() {
+        // [(p0 p1) p2 p3]
+        mInterpolator.reset(mXCoords, mYCoords, p0, p3 + 1);
+        mInterpolator.setInterval(p0 - 1, p0, p1, p1 + 1);
+        assertEquals("p0x", mXCoords[p0], mInterpolator.mP1X);
+        assertEquals("p0y", mYCoords[p0], mInterpolator.mP1Y);
+        assertEquals("p1x", mXCoords[p1], mInterpolator.mP2X);
+        assertEquals("p1y", mYCoords[p1], mInterpolator.mP2Y);
+        // XY-slope at p0=3.0 (-0.75/-0.25)
+        assertFloatEquals("slope x p0", -0.25f, mInterpolator.mSlope1X);
+        assertFloatEquals("slope y p0", -0.75f, mInterpolator.mSlope1Y);
+        // XY-slope at p1=1/3.0 (0.50/1.50)
+        assertFloatEquals("slope x p1",  1.50f, mInterpolator.mSlope2X);
+        assertFloatEquals("slope y p1",  0.50f, mInterpolator.mSlope2Y);
+        // t=0.0 (p0)
+        mInterpolator.interpolate(0.0f);
+        assertFloatEquals("t=0.0 x", 0.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.0 y", 1.0f, mInterpolator.mInterpolatedY);
+        // t=0.2
+        mInterpolator.interpolate(0.2f);
+        assertFloatEquals("t=0.2 x", 0.02400f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.2 y", 0.78400f, mInterpolator.mInterpolatedY);
+        // t=0.5
+        mInterpolator.interpolate(0.5f);
+        assertFloatEquals("t=0.5 x", 0.28125f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.5 y", 0.34375f, mInterpolator.mInterpolatedY);
+        // t=0.8
+        mInterpolator.interpolate(0.8f);
+        assertFloatEquals("t=0.8 x", 0.69600f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.8 y", 0.01600f, mInterpolator.mInterpolatedY);
+        // t=1.0 (p1)
+        mInterpolator.interpolate(1.0f);
+        assertFloatEquals("t=1.0 x", 1.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=1.0 y", 0.0f, mInterpolator.mInterpolatedY);
+    }
+
+    public void testP1P2() {
+        // [p0 (p1 p2) p3]
+        mInterpolator.reset(mXCoords, mYCoords, p0, p3 + 1);
+        mInterpolator.setInterval(p1 - 1, p1, p2, p2 + 1);
+        assertEquals("p1x", mXCoords[p1], mInterpolator.mP1X);
+        assertEquals("p1y", mYCoords[p1], mInterpolator.mP1Y);
+        assertEquals("p2x", mXCoords[p2], mInterpolator.mP2X);
+        assertEquals("p2y", mYCoords[p2], mInterpolator.mP2Y);
+        // XY-slope at p1=1/3.0 (0.50/1.50)
+        assertFloatEquals("slope x p1",  1.50f, mInterpolator.mSlope1X);
+        assertFloatEquals("slope y p1",  0.50f, mInterpolator.mSlope1Y);
+        // XY-slope at p2=3.0 (1.50/0.50)
+        assertFloatEquals("slope x p2",  0.50f, mInterpolator.mSlope2X);
+        assertFloatEquals("slope y p2",  1.50f, mInterpolator.mSlope2Y);
+        // t=0.0 (p1)
+        mInterpolator.interpolate(0.0f);
+        assertFloatEquals("t=0.0 x", 1.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.0 y", 0.0f, mInterpolator.mInterpolatedY);
+        // t=0.2
+        mInterpolator.interpolate(0.2f);
+        assertFloatEquals("t=0.2 x", 1.384f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.2 y", 0.224f, mInterpolator.mInterpolatedY);
+        // t=0.5
+        mInterpolator.interpolate(0.5f);
+        assertFloatEquals("t=0.5 x", 2.125f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.5 y", 0.875f, mInterpolator.mInterpolatedY);
+        // t=0.8
+        mInterpolator.interpolate(0.8f);
+        assertFloatEquals("t=0.8 x", 2.776f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.8 y", 1.616f, mInterpolator.mInterpolatedY);
+        // t=1.0 (p2)
+        mInterpolator.interpolate(1.0f);
+        assertFloatEquals("t=1.0 x", 3.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=1.0 y", 2.0f, mInterpolator.mInterpolatedY);
+    }
+
+    public void testP2P3() {
+        // [p0 p1 (p2 p3)]
+        mInterpolator.reset(mXCoords, mYCoords, p0, p3 + 1);
+        mInterpolator.setInterval(p2 - 1, p2, p3, p3 + 1);
+        assertEquals("p2x", mXCoords[p2], mInterpolator.mP1X);
+        assertEquals("p2y", mYCoords[p2], mInterpolator.mP1Y);
+        assertEquals("p3x", mXCoords[p3], mInterpolator.mP2X);
+        assertEquals("p3y", mYCoords[p3], mInterpolator.mP2Y);
+        // XY-slope at p2=3.0 (1.50/0.50)
+        assertFloatEquals("slope x p2",  0.50f, mInterpolator.mSlope1X);
+        assertFloatEquals("slope y p2",  1.50f, mInterpolator.mSlope1Y);
+        // XY-slope at p3=1/3.0 (-0.25/-0.75)
+        assertFloatEquals("slope x p3", -0.75f, mInterpolator.mSlope2X);
+        assertFloatEquals("slope y p3", -0.25f, mInterpolator.mSlope2Y);
+        // t=0.0 (p2)
+        mInterpolator.interpolate(0.0f);
+        assertFloatEquals("t=0.0 x", 3.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.0 y", 2.0f, mInterpolator.mInterpolatedY);
+        // t=0.2
+        mInterpolator.interpolate(0.2f);
+        assertFloatEquals("t=0.2 x", 2.98400f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.2 y", 2.30400f, mInterpolator.mInterpolatedY);
+        // t=0.5
+        mInterpolator.interpolate(0.5f);
+        assertFloatEquals("t=0.5 x", 2.65625f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.5 y", 2.71875f, mInterpolator.mInterpolatedY);
+        // t=0.8
+        mInterpolator.interpolate(0.8f);
+        assertFloatEquals("t=0.8 x", 2.21600f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.8 y", 2.97600f, mInterpolator.mInterpolatedY);
+        // t=1.0 (p3)
+        mInterpolator.interpolate(1.0f);
+        assertFloatEquals("t=1.0 x", 2.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=1.0 y", 3.0f, mInterpolator.mInterpolatedY);
+    }
+
+    public void testJustP1P2() {
+        // [(p1 p2)]
+        mInterpolator.reset(mXCoords, mYCoords, p1, p2 + 1);
+        mInterpolator.setInterval(p1 - 1, p1, p2, p2 + 1);
+        assertEquals("p1x", mXCoords[p1], mInterpolator.mP1X);
+        assertEquals("p1y", mYCoords[p1], mInterpolator.mP1Y);
+        assertEquals("p2x", mXCoords[p2], mInterpolator.mP2X);
+        assertEquals("p2y", mYCoords[p2], mInterpolator.mP2Y);
+        // XY-slope at p1=1.0 (2.0/2.0)
+        assertFloatEquals("slope x p1", 2.00f, mInterpolator.mSlope1X);
+        assertFloatEquals("slope y p1", 2.00f, mInterpolator.mSlope1Y);
+        // XY-slope at p2=1.0 (2.0/2.0)
+        assertFloatEquals("slope x p2", 2.00f, mInterpolator.mSlope2X);
+        assertFloatEquals("slope y p2", 2.00f, mInterpolator.mSlope2Y);
+        // t=0.0 (p1)
+        mInterpolator.interpolate(0.0f);
+        assertFloatEquals("t=0.0 x", 1.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.0 y", 0.0f, mInterpolator.mInterpolatedY);
+        // t=0.2
+        mInterpolator.interpolate(0.2f);
+        assertFloatEquals("t=0.2 x", 1.4f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.2 y", 0.4f, mInterpolator.mInterpolatedY);
+        // t=0.5
+        mInterpolator.interpolate(0.5f);
+        assertFloatEquals("t=0.5 x", 2.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.5 y", 1.0f, mInterpolator.mInterpolatedY);
+        // t=0.8
+        mInterpolator.interpolate(0.8f);
+        assertFloatEquals("t=0.8 x", 2.6f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=0.8 y", 1.6f, mInterpolator.mInterpolatedY);
+        // t=1.0 (p2)
+        mInterpolator.interpolate(1.0f);
+        assertFloatEquals("t=1.0 x", 3.0f, mInterpolator.mInterpolatedX);
+        assertFloatEquals("t=1.0 y", 2.0f, mInterpolator.mInterpolatedY);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java
index 05f3955..d05aabf 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java
@@ -56,7 +56,8 @@
         return names.toArray(new String[names.size()]);
     }
 
-    private static void assertArrayEquals(String message, Object[] expected, Object[] actual) {
+    private static void assertArrayEquals(final String message, final Object[] expected,
+            final Object[] actual) {
         if (expected == actual) {
             return;
         }
@@ -74,14 +75,15 @@
         }
     }
 
-    private void assertTextArray(String message, String value, String ... expectedArray) {
+    private void assertTextArray(final String message, final String value,
+            final String ... expectedArray) {
         final String resolvedActual = KeySpecParser.resolveTextReference(value, mTextsSet);
         final String[] actual = StringUtils.parseCsvString(resolvedActual);
         final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
         assertArrayEquals(message, expected, actual);
     }
 
-    private void assertError(String message, String value, String ... expected) {
+    private void assertError(final String message, final String value, final String ... expected) {
         try {
             assertTextArray(message, value, expected);
             fail(message);
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 4ccbf48..4583eab 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -36,6 +36,7 @@
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
 import java.util.Locale;
 
@@ -130,7 +131,9 @@
     protected void setUp() throws Exception {
         super.setUp();
         mTextView = new MyTextView(getContext());
-        mTextView.setInputType(InputType.TYPE_CLASS_TEXT);
+        final int inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+                | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+        mTextView.setInputType(inputType);
         mTextView.setEnabled(true);
         setupService();
         mLatinIME = getService();
@@ -138,9 +141,7 @@
         mLatinIME.onCreate();
         setDebugMode(previousDebugSetting);
         final EditorInfo ei = new EditorInfo();
-        ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
         final InputConnection ic = mTextView.onCreateInputConnection(ei);
-        ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
         final LayoutInflater inflater =
                 (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         final ViewGroup vg = new FrameLayout(getContext());
@@ -181,17 +182,21 @@
         // a message that calls it instead of calling it directly.
         Looper.loop();
 
-        // Once #quit() has been called, the message queue has an "mQuiting" field that prevents
-        // any subsequent post in this queue. However the queue itself is still fully functional!
-        // If we have a way of resetting "queue.mQuiting" then we can continue using it as normal,
-        // coming back to this method to run the messages.
+        // Once #quit() has been called, the looper is not functional any more (it used to be,
+        // but now it SIGSEGV's if it's used again).
+        // It won't accept creating a new looper for this thread and switching to it...
+        // ...unless we can trick it into throwing out the old looper and believing it hasn't
+        // been initialized before.
         MessageQueue queue = Looper.myQueue();
         try {
-            // However there is no way of doing it externally, and mQuiting is private.
+            // However there is no way of doing it externally, and the static ThreadLocal
+            // field into which it's stored is private.
             // So... get out the big guns.
-            java.lang.reflect.Field f = MessageQueue.class.getDeclaredField("mQuiting");
-            f.setAccessible(true); // What do you mean "private"?
-            f.setBoolean(queue, false);
+            java.lang.reflect.Field f = Looper.class.getDeclaredField("sThreadLocal");
+            f.setAccessible(true); // private lolwut
+            final ThreadLocal<Looper> a = (ThreadLocal<Looper>) f.get(looper);
+            a.set(null);
+            looper.prepare();
         } catch (NoSuchFieldException e) {
             throw new RuntimeException(e);
         } catch (IllegalAccessException e) {
@@ -251,7 +256,8 @@
     }
 
     protected void pickSuggestionManually(final int index, final String suggestion) {
-        mLatinIME.pickSuggestionManually(index, suggestion);
+        mLatinIME.pickSuggestionManually(index, new SuggestedWordInfo(suggestion, 1,
+                SuggestedWordInfo.KIND_CORRECTION, "main"));
     }
 
     // Helper to avoid writing the try{}catch block each time
diff --git a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
index 923ab2e..966919e 100644
--- a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
@@ -19,6 +19,8 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import java.util.Locale;
+
 @SmallTest
 public class StringUtilsTests extends AndroidTestCase {
     public void testContainsInArray() {
@@ -90,4 +92,48 @@
         assertEquals("in 5 elements at position 2,4", "key1,key3,key5",
                 StringUtils.removeFromCsvIfExists("key", "key1,key,key3,key,key5"));
     }
+
+    public void testToTitleCase() {
+        assertEquals("SSaa",
+                StringUtils.toTitleCase("ßaa", Locale.GERMAN));
+        assertEquals("Aßa",
+                StringUtils.toTitleCase("aßa", Locale.GERMAN));
+        assertEquals("Iab",
+                StringUtils.toTitleCase("iab", Locale.ENGLISH));
+        assertEquals("Camelcase",
+                StringUtils.toTitleCase("cAmElCaSe", Locale.ENGLISH));
+        assertEquals("İab",
+                StringUtils.toTitleCase("iab", new Locale("tr")));
+        assertEquals("Aib",
+                StringUtils.toTitleCase("AİB", new Locale("tr")));
+        // For one character, toTitleCase returns the string as is. Not sure what the motivation
+        // is, but that's how it works now.
+        assertEquals("a",
+                StringUtils.toTitleCase("a", Locale.ENGLISH));
+        assertEquals("A",
+                StringUtils.toTitleCase("A", Locale.ENGLISH));
+    }
+
+    public void testGetCapitalizationType() {
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("capitalize"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("cApITalize"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("capitalizE"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("__c a piu$@tali56ze"));
+        assertEquals(StringUtils.CAPITALIZE_FIRST,
+                StringUtils.getCapitalizationType("A__c a piu$@tali56ze"));
+        assertEquals(StringUtils.CAPITALIZE_FIRST,
+                StringUtils.getCapitalizationType("Capitalize"));
+        assertEquals(StringUtils.CAPITALIZE_FIRST,
+                StringUtils.getCapitalizationType("     Capitalize"));
+        assertEquals(StringUtils.CAPITALIZE_ALL,
+                StringUtils.getCapitalizationType("CAPITALIZE"));
+        assertEquals(StringUtils.CAPITALIZE_ALL,
+                StringUtils.getCapitalizationType("  PI26LIE"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType(""));
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
index ade0109..bd87292 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
@@ -72,15 +72,12 @@
     private static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE =
             new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */);
 
-    private static final String[] CHARACTERS = {
-        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
-        "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
-    };
-
     public BinaryDictIOTests() {
         super();
 
-        final Random random = new Random(123456);
+        final long time = System.currentTimeMillis();
+        Log.e(TAG, "Testing dictionary: seed is " + time);
+        final Random random = new Random(time);
         sWords.clear();
         generateWords(MAX_UNIGRAMS, random);
 
@@ -132,13 +129,16 @@
     /**
      * Generates a random word.
      */
-    private String generateWord(final int value) {
-        final int lengthOfChars = CHARACTERS.length;
+    private String generateWord(final Random random) {
         StringBuilder builder = new StringBuilder("a");
-        long lvalue = Math.abs((long)value);
-        while (lvalue > 0) {
-            builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
-            lvalue /= lengthOfChars;
+        int count = random.nextInt() % 30; // Arbitrarily 30 chars max
+        while (count > 0) {
+            final long r = Math.abs(random.nextInt());
+            if (r < 0) continue;
+            // Don't insert 0~20, but insert any other code point.
+            // Code points are in the range 0~0x10FFFF.
+            builder.appendCodePoint((int)(20 + r % (0x10FFFF - 20)));
+            --count;
         }
         return builder.toString();
     }
@@ -146,7 +146,7 @@
     private void generateWords(final int number, final Random random) {
         final Set<String> wordSet = CollectionUtils.newHashSet();
         while (wordSet.size() < number) {
-            wordSet.add(generateWord(random.nextInt()));
+            wordSet.add(generateWord(random));
         }
         sWords.addAll(wordSet);
     }
@@ -555,7 +555,7 @@
         // Test a word that isn't contained within the dictionary.
         final Random random = new Random((int)System.currentTimeMillis());
         for (int i = 0; i < 1000; ++i) {
-            final String word = generateWord(random.nextInt());
+            final String word = generateWord(random);
             if (sWords.indexOf(word) != -1) continue;
             runGetTerminalPosition(buffer, word, i, false);
         }
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
new file mode 100644
index 0000000..fe3781d
--- /dev/null
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.makedict.FusionDictionary;
+import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
+import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
+import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
+import com.android.inputmethod.latin.makedict.Word;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Random;
+
+/**
+ * Unit tests for BinaryDictInputOutput.
+ */
+public class FusionDictionaryTest extends TestCase {
+    private static final ArrayList<String> sWords = new ArrayList<String>();
+    private static final int MAX_UNIGRAMS = 1000;
+
+    private void prepare(final long seed) {
+        System.out.println("Seed is " + seed);
+        final Random random = new Random(seed);
+        sWords.clear();
+        generateWords(MAX_UNIGRAMS, random);
+    }
+
+    /**
+     * Generates a random word.
+     */
+    private String generateWord(final Random random) {
+        StringBuilder builder = new StringBuilder("a");
+        int count = random.nextInt() % 30;
+        while (count > 0) {
+            final long r = Math.abs(random.nextInt());
+            if (r < 0) continue;
+            // Don't insert 0~20, but insert any other code point.
+            // Code points are in the range 0~0x10FFFF.
+            if (builder.length() < 7)
+                builder.appendCodePoint((int)(20 +r % (0x10FFFF - 20)));
+            --count;
+        }
+        if (builder.length() == 1) return generateWord(random);
+        return builder.toString();
+    }
+
+    private void generateWords(final int number, final Random random) {
+        while (sWords.size() < number) {
+            sWords.add(generateWord(random));
+        }
+    }
+
+    private void checkDictionary(final FusionDictionary dict, final ArrayList<String> words,
+            int limit) {
+        assertNotNull(dict);
+        for (final String word : words) {
+            if (--limit < 0) return;
+            final CharGroup cg = FusionDictionary.findWordInTree(dict.mRoot, word);
+            if (null == cg) {
+                System.out.println("word " + dumpWord(word));
+                dumpDict(dict);
+            }
+            assertNotNull(cg);
+        }
+    }
+
+    private String dumpWord(final String word) {
+        final StringBuilder sb = new StringBuilder("");
+        for (int i = 0; i < word.length(); i = word.offsetByCodePoints(i, 1)) {
+            sb.append(word.codePointAt(i));
+            sb.append(" ");
+        }
+        return sb.toString();
+    }
+
+    private void dumpDict(final FusionDictionary dict) {
+        for (Word w : dict) {
+            System.out.println("Word " + dumpWord(w.mWord));
+        }
+    }
+
+    // Test the flattened array contains the expected number of nodes, and
+    // that it does not contain any duplicates.
+    public void testFusion() {
+        final FusionDictionary dict = new FusionDictionary(new Node(),
+                new DictionaryOptions(new HashMap<String, String>(),
+                        false /* germanUmlautProcessing */, false /* frenchLigatureProcessing */));
+        final long time = System.currentTimeMillis();
+        prepare(time);
+        for (int i = 0; i < sWords.size(); ++i) {
+            System.out.println("Adding in pos " + i + " : " + dumpWord(sWords.get(i)));
+            dict.add(sWords.get(i), 180, null, false);
+            dumpDict(dict);
+            checkDictionary(dict, sWords, i);
+        }
+    }
+}
diff --git a/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl b/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
index 2409bfc..2fc97b5 100644
--- a/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
+++ b/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
@@ -21,7 +21,6 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.R;
 
 import java.util.HashMap;
 
@@ -61,13 +60,14 @@
         }
     }
 
-    public void loadStringResources(Context context) {
-        loadStringResourcesInternal(context, RESOURCE_NAMES, R.string.english_ime_name);
+    public void loadStringResources(final Context context) {
+        final int referenceId = context.getApplicationInfo().labelRes;
+        loadStringResourcesInternal(context, RESOURCE_NAMES, referenceId);
     }
 
     @UsedForTesting
-    void loadStringResourcesInternal(Context context, final String[] resourceNames,
-            int referenceId) {
+    void loadStringResourcesInternal(final Context context, final String[] resourceNames,
+            final int referenceId) {
         final Resources res = context.getResources();
         final String packageName = res.getResourcePackageName(referenceId);
         for (final String resName : resourceNames) {